Netdev List
 help / color / mirror / Atom feed
* [PATCH] rtase: Workaround for IP fragmented UDP packet hardware bug
@ 2026-06-01  6:23 Justin Lai
  2026-06-01 13:20 ` Andrew Lunn
  2026-06-01 13:22 ` Alexander Lobakin
  0 siblings, 2 replies; 7+ messages in thread
From: Justin Lai @ 2026-06-01  6:23 UTC (permalink / raw)
  To: kuba
  Cc: davem, edumazet, pabeni, andrew+netdev, linux-kernel, netdev,
	horms, pkshih, larry.chiu, Justin Lai

The hardware parser incorrectly interprets 319/320 in a short
IP fragmented UDP packet payload as standard PTP destination
ports and treats the fragment as a PTP packet for further
parsing.

If the transport data is smaller than RTASE_MIN_PAD_LEN, the
remaining data is insufficient for further parsing and causes
hardware TX hang.

Pad these packets so the transport data reaches
RTASE_MIN_PAD_LEN before transmitting to avoid triggering the
hardware issue.

Signed-off-by: Justin Lai <justinlai0215@realtek.com>
---
 drivers/net/ethernet/realtek/rtase/rtase.h    |  3 ++
 .../net/ethernet/realtek/rtase/rtase_main.c   | 50 +++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/drivers/net/ethernet/realtek/rtase/rtase.h b/drivers/net/ethernet/realtek/rtase/rtase.h
index 9bd6872474c1..213fe2173b40 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase.h
+++ b/drivers/net/ethernet/realtek/rtase/rtase.h
@@ -363,4 +363,7 @@ struct rtase_private {
 
 #define RTASE_MSS_MASK GENMASK(28, 18)
 
+#define RTASE_MIN_PAD_LEN      47
+#define RTASE_SHORT_PKT_THRESH 128
+
 #endif /* RTASE_H */
diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c
index bde9bccfb5a9..43a4aa275b62 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
+++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
@@ -61,6 +61,7 @@
 #include <linux/pci.h>
 #include <linux/pm_runtime.h>
 #include <linux/prefetch.h>
+#include <linux/ptp_classify.h>
 #include <linux/rtnetlink.h>
 #include <linux/tcp.h>
 #include <asm/irq.h>
@@ -1250,6 +1251,52 @@ static u32 rtase_tx_csum(struct sk_buff *skb, const struct net_device *dev)
 	return csum_cmd;
 }
 
+static bool rtase_skb_is_udp(struct sk_buff *skb)
+{
+	int no = skb_network_offset(skb);
+	struct ipv6hdr *i6h, _i6h;
+	struct iphdr *ih, _ih;
+
+	switch (vlan_get_protocol(skb)) {
+	case htons(ETH_P_IP):
+		ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih);
+		return ih && ih->protocol == IPPROTO_UDP;
+	case htons(ETH_P_IPV6):
+		i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h);
+		return i6h && i6h->nexthdr == IPPROTO_UDP;
+	default:
+		return false;
+	}
+}
+
+static bool rtase_skb_pad(struct sk_buff *skb)
+{
+	bool has_trans = skb_transport_header_was_set(skb);
+	u32 pkt_len = skb->len;
+	u32 trans_data_len;
+	u16 dest_port;
+	u32 pad_len;
+
+	if (!(has_trans &&
+	      pkt_len < RTASE_SHORT_PKT_THRESH + RTASE_MIN_PAD_LEN &&
+	      rtase_skb_is_udp(skb)))
+		return true;
+
+	trans_data_len = skb_tail_pointer(skb) - skb_transport_header(skb);
+	if (trans_data_len >= offsetof(struct udphdr, len) &&
+	    trans_data_len < RTASE_MIN_PAD_LEN) {
+		dest_port = ntohs(udp_hdr(skb)->dest);
+
+		if (dest_port == PTP_EV_PORT || dest_port == PTP_GEN_PORT) {
+			pad_len = RTASE_MIN_PAD_LEN - trans_data_len;
+			if (__skb_put_padto(skb, skb->len + pad_len, false))
+				return false;
+		}
+	}
+
+	return true;
+}
+
 static int rtase_xmit_frags(struct rtase_ring *ring, struct sk_buff *skb,
 			    u32 opts1, u32 opts2)
 {
@@ -1363,6 +1410,9 @@ static netdev_tx_t rtase_start_xmit(struct sk_buff *skb,
 		opts2 |= rtase_tx_csum(skb, dev);
 	}
 
+	if (!rtase_skb_pad(skb))
+		goto err_dma_0;
+
 	frags = rtase_xmit_frags(ring, skb, opts1, opts2);
 	if (unlikely(frags < 0))
 		goto err_dma_0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-06-04 14:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-01  6:23 [PATCH] rtase: Workaround for IP fragmented UDP packet hardware bug Justin Lai
2026-06-01 13:20 ` Andrew Lunn
2026-06-04  8:33   ` Justin Lai
2026-06-04 11:46     ` David Laight
2026-06-04 13:43       ` Justin Lai
2026-06-04 14:53         ` David Laight
2026-06-01 13:22 ` Alexander Lobakin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox