The Linux Kernel Mailing List
 help / color / mirror / Atom feed
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.

  reply	other threads:[~2026-08-25 15:04 UTC|newest]

Thread overview: 4+ 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-24 13:47 ` [PATCH net 2/2] net: macb: fix zero UDPv4 checksum on transmit Nicolai Buchwitz

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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox