[PATCH net-next 6/7] hinic: Don't do TX csum offload with routing header present
From: Tom Herbert <hidden>
Date: 2024-07-01 01:21:32
Subsystem:
huawei ethernet driver, networking drivers, the rest · Maintainers:
Cai Huoqing, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Tom Herbert <redacted> When determining if the L4 checksum in an IPv6 packet can be offloaded on transmit, call ipv6_skip_exthdr_no_rthdr to check for the presence of a routing header. If a routing header is present, that is the function return less than zero, then don't offload checksum and call skb_checksum_help instead. Signed-off-by: Tom Herbert <redacted> --- drivers/net/ethernet/huawei/hinic/hinic_tx.c | 23 +++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
index 9b60966736db..ba6b7481b6fa 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c@@ -357,8 +357,10 @@ static int offload_csum(struct hinic_sq_task *task, u32 *queue_info, u32 offset, l4_len, network_hdr_len; enum hinic_l3_offload_type l3_type; u32 tunnel_type = NOT_TUNNEL; + unsigned char *exthdr; union hinic_l3 ip; union hinic_l4 l4; + __be16 frag_off; u8 l4_proto; if (skb->ip_summed != CHECKSUM_PARTIAL)
@@ -374,17 +376,15 @@ static int offload_csum(struct hinic_sq_task *task, u32 *queue_info, l3_type = IPV4_PKT_NO_CHKSUM_OFFLOAD; l4_proto = ip.v4->protocol; } else if (ip.v4->version == 6) { - unsigned char *exthdr; - __be16 frag_off; - l3_type = IPV6_PKT; tunnel_type = TUNNEL_UDP_CSUM; exthdr = ip.hdr + sizeof(*ip.v6); l4_proto = ip.v6->nexthdr; l4.hdr = skb_transport_header(skb); - if (l4.hdr != exthdr) - ipv6_skip_exthdr(skb, exthdr - skb->data, - &l4_proto, &frag_off); + if (l4.hdr != exthdr && + ipv6_skip_exthdr_no_rthdr(skb, exthdr - skb->data, + &l4_proto, &frag_off) < 0) + goto no_csum_offload; } else { l3_type = L3TYPE_UNKNOWN; l4_proto = IPPROTO_RAW;
@@ -411,6 +411,7 @@ static int offload_csum(struct hinic_sq_task *task, u32 *queue_info, network_hdr_len = skb_network_header_len(skb); break; default: +no_csum_offload: /* Unsupported tunnel packet, disable csum offload */ skb_checksum_help(skb); return 0;
@@ -421,6 +422,16 @@ static int offload_csum(struct hinic_sq_task *task, u32 *queue_info, ip.hdr = skb_network_header(skb); l4.hdr = skb_transport_header(skb); network_hdr_len = skb_network_header_len(skb); + + if (ip.v4->version == 6) { + exthdr = ip.hdr + sizeof(*ip.v6); + l4_proto = ip.v6->nexthdr; + l4.hdr = skb_transport_header(skb); + if (l4.hdr != exthdr && + ipv6_skip_exthdr_no_rthdr(skb, exthdr - skb->data, + &l4_proto, &frag_off) < 0) + goto no_csum_offload; + } } get_inner_l3_l4_type(skb, &ip, &l4, TX_OFFLOAD_CSUM, &l3_type,
--
2.34.1