From: Nicolai Buchwitz <nb@tipi-net.de>
To: "Théo Lebrun" <theo.lebrun@bootlin.com>
Cc: Conor Dooley <conor.dooley@microchip.com>,
Claudiu Beznea <claudiu.beznea@tuxon.dev>,
Jonathan Bell <jonathan@raspberrypi.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Richard Cochran <richardcochran@gmail.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net 1/2] net: macb: exclude software FCS from TX byte statistics
Date: Tue, 25 Aug 2026 17:04:14 +0200 [thread overview]
Message-ID: <d1f02ab923c0464fa73cafa75a21943d@tipi-net.de> (raw)
In-Reply-To: <20260824134703.766708-2-nb@tipi-net.de>
Replying to netdev's sashiko
https://netdev-ai.bots.linux.dev/sashiko/#/message/20260824134703.766708-2-nb%40tipi-net.de:
> --- Patch [1]: [PATCH net 1/2] net: macb: exclude software FCS from TX
> byte statistics ---
> commit 24acee751440b1a44c9e16688554df0848ab621a
> Author: Nicolai Buchwitz <nb@tipi-net.de>
>
> net: macb: exclude software FCS from TX byte statistics
>
> Frames going through macb_pad_and_fcs() get padded and four FCS
> bytes appended, and TX completion then accounts the grown skb->len.
> tx_bytes is supposed to exclude the FCS, and frames padded by the
> hardware are counted without the padding anyway, so these frames
> show up too large in the statistics.
>
> > diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
> > index 76ee4f5060335..623d072a271d0 100644
> > --- a/drivers/net/ethernet/cadence/macb_main.c
> > +++ b/drivers/net/ethernet/cadence/macb_main.c
> > @@ -1322,8 +1322,8 @@ static void macb_tx_error_task(struct work_struct *work)
> > bp->netdev->stats.tx_packets++;
> > queue->stats.tx_packets++;
> > packets++;
> > - bp->netdev->stats.tx_bytes += skb->len;
> > - queue->stats.tx_bytes += skb->len;
> > + bp->netdev->stats.tx_bytes += tx_skb->skb_len;
> > + queue->stats.tx_bytes += tx_skb->skb_len;
> > bytes += skb->len;
> > }
> > } else {
>
> This is a pre-existing issue, but does macb_tx_error_task() leak BQL
> bytes for
> dropped pending packets?
>
> When recovering from a TX error, macb_tx_error_task() iterates through
> the TX
> ring. For pending descriptors that did not successfully transmit, the
> code calls
> macb_tx_unmap(bp, tx_skb, 0) which frees the SKB.
>
> However, it appears to fail to accumulate the freed SKB's length into
> the bytes
> accumulator. When netdev_tx_completed_queue() is subsequently called,
> these
> leaked bytes are never reported to BQL, which could permanently retain
> these
> charged bytes and stall the TX queue.
Looks like it. The dropped frames never get a completion credit, and DQL
only gets reset on close. This is independent of the statistics change,
so I would address it in a follow-up fix. Objections?
> This is another pre-existing issue, but does macb_tx_error_task()
> modify the TX
> ring pointers without holding the appropriate lock?
>
> macb_tx_error_task() acquires bp->lock and issues a non-blocking stop
> to the
> queues via netif_tx_stop_all_queues(). It then manipulates the ring
> pointers
> queue->tx_head and queue->tx_tail.
>
> However, the fast-path macb_start_xmit() protects these identical
> pointers
> using queue->tx_ptr_lock.
>
> Since netif_tx_stop_all_queues() does not wait for an already-running
> macb_start_xmit() to complete, could macb_tx_error_task() zero out the
> ring
> pointers while macb_start_xmit() is concurrently populating descriptors
> on
> another CPU?
AFAIU yes, stopping the queues doesn't wait for a start_xmit that's
already running. Taking tx_ptr_lock there before bp->lock, in the same
order as start_xmit, should fix that. I would handle this together with
the
BQL issue in a follow-up series.
> [ ... ]
> > @@ -2485,6 +2487,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb,
> > return ret;
> > }
> >
> > + skb_len = skb->len;
> > if (macb_pad_and_fcs(&skb, netdev)) {
>
> This isn't a bug introduced by this patch, but does macb_pad_and_fcs()
> append
> an FCS before verifying TX ring space, which could corrupt the SKB upon
> retry?
>
> [ ... ]
>
> Because the network stack will subsequently retry transmitting this
> identical
> SKB, and its length is now larger, will macb_pad_and_fcs() compute a
> new CRC
> over the old FCS and append a second, duplicate FCS, eventually
> corrupting the
> payload once tailroom is exhausted?
Yes, and the copy path looks worse: the stack can requeue an skb the
driver already
consumed. I'll do the ring space check before touching the skb at all.
After that
point the driver never returns NETDEV_TX_BUSY, so swapping the skb
should be fine.
> This is also a pre-existing issue, but does macb_pad_and_fcs() modify
> shared SKB
> data for cloned packets and break nonlinear SKB layouts?
>
> If an SKB is cloned (e.g., multicast, TCP retransmissions) or nonlinear
> (paged
> fragments), and its length is already >= ETH_ZLEN (60 bytes) so padlen
> <= 0,
> and it has at least 4 bytes of tailroom, the code skips the
> reallocation check:
>
> if (padlen <= 0) {
> /* FCS could be appeded to tailroom. */
> if (tailroom >= ETH_FCS_LEN)
> goto add_fcs;
>
> It then directly appends 4 bytes of FCS via skb_put_u8(). For cloned
> SKBs, this
> modifies shared memory data. For nonlinear SKBs, skb_put() illegally
> extends the
> linear part, which could trigger a panic in skb_panic().
The cloned part looks right. The nonlinear case IMHO can't trigger
today:
skb_tailroom() is 0 for nonlinear skbs, so they go down
skb_copy_expand(),
which linearizes them anyway.
I'll order the cloned check before the in-place FCS path.
next prev parent reply other threads:[~2026-08-25 15:04 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-24 13:47 [PATCH net 0/2] net: macb: fix zero UDPv4 checksum on transmit Nicolai Buchwitz
2026-08-24 13:47 ` [PATCH net 1/2] net: macb: exclude software FCS from TX byte statistics Nicolai Buchwitz
2026-08-25 15:04 ` Nicolai Buchwitz [this message]
2026-08-27 8:52 ` Paolo Abeni
2026-08-28 8:10 ` Nicolai Buchwitz
2026-08-27 18:56 ` Jakub Kicinski
2026-08-28 8:20 ` Nicolai Buchwitz
2026-08-28 13:02 ` David Laight
2026-08-28 8:37 ` David Laight
2026-08-24 13:47 ` [PATCH net 2/2] net: macb: fix zero UDPv4 checksum on transmit Nicolai Buchwitz
2026-08-28 6:04 ` [PATCH net 0/2] " Alexander Dahl
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=d1f02ab923c0464fa73cafa75a21943d@tipi-net.de \
--to=nb@tipi-net.de \
--cc=andrew+netdev@lunn.ch \
--cc=claudiu.beznea@tuxon.dev \
--cc=conor.dooley@microchip.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jonathan@raspberrypi.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=richardcochran@gmail.com \
--cc=theo.lebrun@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 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.