[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
<DM3PR11MB8736CCEC9ADD424FEE973E1DEC8AA@DM3PR11MB8736.namprd11.prod.outlook.com>
Date: Fri, 9 May 2025 22:18:17 +0000
From: <Tristram.Ha@...rochip.com>
To: <jakobunt@...il.com>
CC: <quentin.schulz@...rry.de>, <jakob.unterwurzacher@...rry.de>,
<netdev@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
<Woojung.Huh@...rochip.com>, <UNGLinuxDriver@...rochip.com>,
<andrew@...n.ch>, <olteanv@...il.com>, <davem@...emloft.net>,
<edumazet@...gle.com>, <kuba@...nel.org>, <pabeni@...hat.com>,
<horms@...nel.org>
Subject: RE: [PATCH] net: dsa: microchip: linearize skb for tail-tagging
switches
> The pointer arithmentic for accessing the tail tag does not
> seem to handle nonlinear skbs.
>
> For nonlinear skbs, it reads uninitialized memory inside the
> skb headroom, essentially randomizing the tag, breaking user
> traffic.
>
> Example where ksz9477_rcv thinks that the packet from port 1 comes
> from port 6 (which does not exist for the ksz9896 that's in use),
> dropping the packet. Debug prints added by me (not included in
> this patch):
>
> [ 256.645337] ksz9477_rcv:323 tag0=6
> [ 256.645349] skb len=47 headroom=78 headlen=0 tailroom=0
> mac=(64,14) mac_len=14 net=(78,0) trans=78
> shinfo(txflags=0 nr_frags=1 gso(size=0 type=0 segs=0))
> csum(0x0 start=0 offset=0 ip_summed=0 complete_sw=0 valid=0
> level=0)
> hash(0x0 sw=0 l4=0) proto=0x00f8 pkttype=1 iif=3
> priority=0x0 mark=0x0 alloc_cpu=0 vlan_all=0x0
> encapsulation=0 inner(proto=0x0000, mac=0, net=0, trans=0)
> [ 256.645377] dev name=end1 feat=0x0002e10200114bb3
> [ 256.645386] skb headroom: 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00
> [ 256.645395] skb headroom: 00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00
> [ 256.645403] skb headroom: 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00
> [ 256.645411] skb headroom: 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00
> [ 256.645420] skb headroom: 00000040: ff ff ff ff ff ff 00 1c 19 f2 e2 db 08 06
> [ 256.645428] skb frag: 00000000: 00 01 08 00 06 04 00 01 00 1c 19 f2 e2 db
> 0a 02
> [ 256.645436] skb frag: 00000010: 00 83 00 00 00 00 00 00 0a 02 a0 2f 00 00
> 00 00
> [ 256.645444] skb frag: 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 01
> [ 256.645452] ksz_common_rcv:92 dsa_conduit_find_user returned NULL
>
> Call skb_linearize before trying to access the tag.
>
> This patch fixes ksz9477_rcv which is used by the ksz9896 I have at
> hand, and also applies the same fix to ksz8795_rcv which seems to have
> the same problem.
>
> Tested on v6.12.19 and today's master (d76bb1ebb5587f66b).
>
> Signed-off-by: Jakob Unterwurzacher <jakob.unterwurzacher@...rry.de>
> ---
> net/dsa/tag_ksz.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
> index c33d4bf17929..7fbcdb7f152a 100644
> --- a/net/dsa/tag_ksz.c
> +++ b/net/dsa/tag_ksz.c
> @@ -140,7 +140,12 @@ static struct sk_buff *ksz8795_xmit(struct sk_buff *skb,
> struct net_device *dev)
>
> static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev)
> {
> - u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
> + u8 *tag;
> +
> + if (skb_linearize(skb))
> + return NULL;
> +
> + tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
>
> return ksz_common_rcv(skb, dev, tag[0] & KSZ8795_TAIL_TAG_EG_PORT_M,
> KSZ_EGRESS_TAG_LEN);
> @@ -311,8 +316,13 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
>
> static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev)
> {
> + u8 *tag;
> +
> + if (skb_linearize(skb))
> + return NULL;
> +
> /* Tag decoding */
> - u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
> + tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
> unsigned int port = tag[0] & KSZ9477_TAIL_TAG_EG_PORT_M;
> unsigned int len = KSZ_EGRESS_TAG_LEN;
>
I am curious about what MAC controller are you using to return socket
buffer with fragments?
I thought DSA already disables most advanced hardware acceleration
features so that the tag manipulation functions do not need to worry
about accessing the socket buffer incorrectly.
Now that the socket buffer has fragment is it better to remove the tail
tag inside the fragment to preserve the performance of receiving such
socket buffer?
I know using skb_linearize() is an easy fix, but is it worthwhile to
check the receive performance?
This is out of topic.
The transmit performance can be improved by keeping the fragments while
adding the tail tag. At one time there is an API in the kernel to do
that, but it was removed as nobody used it. I see the hardware checksum
generation feature is now preserved so the tag manipulation functions
need to handle it. Is there a way to allocate a few more bytes in the
fragments so that the socket buffer does not need to be consolidated to
add tail tag?
Powered by blists - more mailing lists