From: Florian Fainelli <florian.fainelli@broadcom.com>
To: netdev-bot+sashiko@kernel.org
Cc: netdev@vger.kernel.org, jonas.gorski@gmail.com, andrew@lunn.ch,
olteanv@gmail.com, davem@davemloft.net, edumazet@kernel.org,
kuba@kernel.org, pabeni@redhat.com, vivien.didelot@gmail.com,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH net v3 4/8] net: dsa: b53: reject conflicting mirror destinations
Date: Mon, 9 Nov 2026 15:57:18 -0800 [thread overview]
Message-ID: <c7ed60fe-eddd-43b5-9576-f574b5dd80da@broadcom.com> (raw)
In-Reply-To: <179348376172.3131.11440720201294156466@kernel.org>
On 10/31/26 14:56, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential
> issue(s) to consider.
>
> Critical: 0 · High: 0 · Medium: 1 (1) · Low: 1
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [Medium] At this commit, the new conflict check in b53_mirror_add()
> (drivers/net/dsa/b53/b53_common.c:2553-2557) decides whether rules…
> - [Low] The commit message says the patch propagates a failed capture-
> control read, but only the B53_MIR_CAP_CTL read in b53_mirror_add()…
>
> Pre-existing issues:
> - [Medium] Each per-port, per-direction mirror source bit is shared by
> every tc matchall mirror rule on that port and direction, but it is…
>
> --
>
> net: dsa: b53: reject conflicting mirror destinations
>
> With this patch, b53_mirror_add() reads B53_MIR_CAP_CTL first. While
> MIRROR_EN is set, it rejects a new mirror rule whose destination differs
> from the one already programmed. b53_mirror_del() now clears the whole
> CAP_PORT_MASK field along with MIRROR_EN when the last source is removed.
>
>> diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
>> index c38e8c5838bd8..378f47e7250cd 100644
>> --- a/drivers/net/dsa/b53/b53_common.c
>> +++ b/drivers/net/dsa/b53/b53_common.c
>> @@ -2543,7 +2543,19 @@ int b53_mirror_add(struct dsa_switch *ds, int port,
>> struct netlink_ext_ack *extack)
>> {
>> struct b53_device *dev = ds->priv;
>> - u16 reg, loc;
>> + u16 reg, loc, cap_ctl;
>> + int ret;
>> +
>> + ret = b53_read16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, &cap_ctl);
>> + if (ret)
>> + return ret;
>> +
>> + if ((cap_ctl & MIRROR_EN) &&
>> + (cap_ctl & CAP_PORT_MASK) != mirror->to_local_port) {
>> + NL_SET_ERR_MSG_MOD(extack,
>> + "Only one mirroring destination is supported");
>> + return -EOPNOTSUPP;
>> + }
>
> [Severity: Medium]
> Can leftover hardware state make this check reject a valid first rule?
>
> The check only looks at MIRROR_EN and CAP_PORT_MASK as read back from
> B53_MIR_CAP_CTL. It doesn't look at B53_IG_MIR_CTL or B53_EG_MIR_CTL.
>
> At this commit, nothing in the setup path writes any of these three
> registers. The only writers are b53_mirror_add() and b53_mirror_del().
> Also, b53_switch_reset() doesn't soft-reset every chip.
>
> Suppose a bootloader, a previous kernel (kexec or warm reboot) or an
> earlier driver bind left MIRROR_EN set with capture port X. The first tc
> mirror rule to any port other than X would then fail with -EOPNOTSUPP and
> "Only one mirroring destination is supported", even though no software
> rule exists. Before this patch, the add path just overwrote the stale
> destination.
>
> The reverse case also seems possible. Stale source bits with MIRROR_EN
> clear pass this check, so those ports end up mirrored. The same stale bits
> also stop b53_mirror_del() from ever clearing MIRROR_EN.
>
> The later patch "net: dsa: b53: harden mirror register programming" in
> this series seems to fix this. It adds b53_mirror_init(), which zeroes all
> three registers from b53_setup() and bcm_sf2_sw_setup(). It also bases the
> occupancy test on the source masks:
>
> if (((reg | other_reg) & MIRROR_MASK) &&
> (cap_ctl & cap_mask) != cap_port) {
>
> Could that be folded into this patch, so this commit doesn't regress on
> its own?
>
>>
>> if (ingress)
>> loc = B53_IG_MIR_CTL;
>> @@ -2554,11 +2566,10 @@ int b53_mirror_add(struct dsa_switch *ds, int port,
>> reg |= BIT(port);
>> b53_write16(dev, B53_MGMT_PAGE, loc, reg);
>>
>> - b53_read16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, ®);
>> - reg &= ~CAP_PORT_MASK;
>> - reg |= mirror->to_local_port;
>> - reg |= MIRROR_EN;
>> - b53_write16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, reg);
>> + cap_ctl &= ~CAP_PORT_MASK;
>> + cap_ctl |= mirror->to_local_port;
>> + cap_ctl |= MIRROR_EN;
>> + b53_write16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, cap_ctl);
>>
>> return 0;
>> }
>
> [Severity: Low]
> The commit message says the patch will "propagate a failed
> capture-control read rather than making the decision from uninitialized
> data". Are the other register accesses here still unchecked?
>
> Just above this hunk, the source mask read is not checked:
>
> b53_read16(dev, B53_MGMT_PAGE, loc, ®);
> reg |= BIT(port);
> b53_write16(dev, B53_MGMT_PAGE, loc, reg);
>
> reg is an uninitialized stack variable. On failure, b53_mdio_read16() and
> b53_spi_read16() return without writing *val. A failed read therefore
> writes garbage back into B53_IG_MIR_CTL or B53_EG_MIR_CTL.
>
> Both writes are unchecked too, and the function returns 0 either way. DSA
> then keeps a mall entry that the hardware never accepted.
>
> The source bit is enabled before B53_MIR_CAP_CTL is written. If the
> capture-control write fails, MIRROR_EN can stay clear, and a later rule to
> a different destination would pass the new guard.
>
> b53_mirror_del() has the same pattern. If its B53_MIR_CAP_CTL read fails,
> reg still holds the other-direction source mask, and that value is written
> into the capture control register:
>
> b53_read16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, ®);
> ...
> b53_write16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, reg);
>
> The later patch "net: dsa: b53: harden mirror register programming" in
> this series seems to fix all of these. Every read and write is checked,
> B53_MIR_CAP_CTL is programmed before the source bit is enabled, and the
> delete path jumps to an error label instead of writing back garbage.
>
>> @@ -2595,10 +2606,8 @@ void b53_mirror_del(struct dsa_switch *ds, int port,
>>
>> b53_read16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, ®);
>> /* Both no longer have ports, let's disable mirroring */
>> - if (loc_disable && other_loc_disable) {
>> - reg &= ~MIRROR_EN;
>> - reg &= ~mirror->to_local_port;
>> - }
>> + if (loc_disable && other_loc_disable)
>> + reg &= ~(MIRROR_EN | CAP_PORT_MASK);
>
> [Severity: Medium]
> This isn't a bug introduced by this patch, but each per-port,
> per-direction source bit is shared by every matchall mirror rule on that
> port and direction, and it is not reference counted.
>
> dsa_user_add_cls_matchall_mirred() in net/dsa/user.c allows several
> identical rules, and each one is tracked as its own mall entry. Earlier in
> b53_mirror_del(), deleting any one of them clears the shared bit:
>
> reg &= ~BIT(port);
>
> With this patch, if that was the last bit, MIRROR_EN and CAP_PORT_MASK are
> cleared as well. Does the remaining rule then stop mirroring in hardware
> while it is still installed? And would the new guard in b53_mirror_add()
> then accept a rule to a different destination?
>
> The later patch "net: dsa: b53: reference count shared mirror source
> bits" in this series seems to fix this. It adds mirror_count[2] to struct
> b53_port, so the hardware is programmed only on the first reference and
> cleared only when the last one goes away:
>
> if (--(*mirror_count))
> return;
>
>> b53_write16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, reg);
>> }
>> EXPORT_SYMBOL(b53_mirror_del);
>
Agreed that the conflict check needs to handle stale hardware state in
the same patch. I’ll fold the mirror initialization and register-access
hardening into this change, along with the shared-source reference
counting, so the fix is complete in isolation.
pw-bot: cr
--
Florian
next prev parent reply other threads:[~2026-11-09 23:57 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 21:16 [PATCH net v3 0/8] net: dsa: b53: Preliminary fixes Florian Fainelli
2026-10-30 21:16 ` [PATCH net v3 1/8] net: dsa: b53: initialize the jumbo frame size register offset Florian Fainelli
2026-10-30 21:16 ` [PATCH net v3 2/8] net: dsa: b53: fix the SRAB grant timeout check Florian Fainelli
2026-10-30 21:16 ` [PATCH net v3 3/8] net: dsa: b53: clear stale state when creating an ARL entry Florian Fainelli
2026-10-31 21:56 ` netdev-bot+sashiko
2026-11-09 23:56 ` Florian Fainelli
2026-10-30 21:16 ` [PATCH net v3 4/8] net: dsa: b53: reject conflicting mirror destinations Florian Fainelli
2026-10-31 21:56 ` netdev-bot+sashiko
2026-11-09 23:53 ` Florian Fainelli
2026-11-09 23:57 ` Florian Fainelli [this message]
2026-10-30 21:16 ` [PATCH net v3 5/8] net: dsa: b53: use the correct override register 2 Gbps bit Florian Fainelli
2026-10-31 21:56 ` netdev-bot+sashiko
2026-11-09 23:58 ` Florian Fainelli
2026-10-30 21:16 ` [PATCH net v3 6/8] net: dsa: b53: reference count shared mirror source bits Florian Fainelli
2026-10-31 21:56 ` netdev-bot+sashiko
2026-11-10 0:03 ` Florian Fainelli
2026-10-30 21:16 ` [PATCH net v3 7/8] net: dsa: b53: harden mirror register programming Florian Fainelli
2026-10-31 21:56 ` netdev-bot+sashiko
2026-11-10 0:06 ` Florian Fainelli
2026-10-30 21:16 ` [PATCH net v3 8/8] net: dsa: b53: fix mirror port encoding on BCM5325 and BCM5365 Florian Fainelli
2026-10-30 22:11 ` [PATCH net v3 0/8] net: dsa: b53: Preliminary fixes Florian Fainelli
-- strict thread matches above, loose matches on Subject: below --
2026-10-30 21:13 Florian Fainelli
2026-10-30 21:13 ` [PATCH net v3 4/8] net: dsa: b53: reject conflicting mirror destinations Florian Fainelli
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=c7ed60fe-eddd-43b5-9576-f574b5dd80da@broadcom.com \
--to=florian.fainelli@broadcom.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=jonas.gorski@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev-bot+sashiko@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
--cc=vivien.didelot@gmail.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®