diff mbox series

[ovs-dev,v4,2/4] netdev-linux: Only repair IP checksum in IPv4.

Message ID 20240215225305.408579-2-mkp@redhat.com
State Accepted
Commit a2d4ad651d8b9b4deda2c19bd7a87bf40f79ddf3
Headers show
Series [ovs-dev,v4,1/4] netdev-linux: Favour inner packet for multi-encapsulated TSO. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/intel-ovs-compilation success test: success

Commit Message

Mike Pattrick Feb. 15, 2024, 10:53 p.m. UTC
Previously a change was added to the vnet prepend code to solve for the
case where no L4 checksum offloading was needed but the L3 checksum
hadn't been calculated. But the added check didn't properly account
for IPv6 traffic.

Fixes: 85bcbbed839a ("userspace: Enable tunnel tests with TSO.")
Reported-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Mike Pattrick <mkp@redhat.com>
---
 lib/dp-packet.h    | 18 +++++++++++++++++-
 lib/netdev-linux.c |  9 +++++----
 2 files changed, 22 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index 802d3f385..770ddc1b9 100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -1184,7 +1184,7 @@  dp_packet_hwol_is_tunnel_vxlan(struct dp_packet *b)
 
 /* Returns 'true' if packet 'b' is marked for outer IPv4 checksum offload. */
 static inline bool
-dp_packet_hwol_is_outer_ipv4_cksum(struct dp_packet *b)
+dp_packet_hwol_is_outer_ipv4_cksum(const struct dp_packet *b)
 {
     return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_OUTER_IP_CKSUM);
 }
@@ -1384,6 +1384,22 @@  dp_packet_ip_checksum_bad(const struct dp_packet *p)
             DP_PACKET_OL_RX_IP_CKSUM_BAD;
 }
 
+/* Return 'true' is packet 'b' is not encapsulated and is marked for IPv4
+ * checksum offload, or if 'b' is encapsulated and the outer layer is marked
+ * for IPv4 checksum offload. IPv6 packets and non offloaded packets return
+ * 'false'. */
+static inline bool
+dp_packet_hwol_l3_csum_ipv4_ol(const struct dp_packet *b)
+{
+    if (dp_packet_hwol_is_outer_ipv4(b)) {
+        return dp_packet_hwol_is_outer_ipv4_cksum(b);
+    } else if (!dp_packet_hwol_is_outer_ipv6(b)) {
+        return dp_packet_hwol_tx_ip_csum(b) &&
+               !dp_packet_ip_checksum_good(b);
+    }
+    return false;
+}
+
 /* Calculate and set the IPv4 header checksum in packet 'p'. */
 static inline void
 dp_packet_ip_set_header_csum(struct dp_packet *p, bool inner)
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 8964cd670..bf91ef462 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -7199,10 +7199,11 @@  netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu)
         /* The packet has good L4 checksum. No need to validate again. */
         vnet->csum_start = vnet->csum_offset = (OVS_FORCE __virtio16) 0;
         vnet->flags = VIRTIO_NET_HDR_F_DATA_VALID;
-        if (!dp_packet_ip_checksum_good(b)) {
-            /* It is possible that L4 is good but the IP checksum isn't
-             * complete. For example in the case of UDP encapsulation of an ARP
-             * packet where the UDP checksum is 0. */
+
+        /* It is possible that L4 is good but the IPv4 checksum isn't
+         * complete. For example in the case of UDP encapsulation of an ARP
+         * packet where the UDP checksum is 0. */
+        if (dp_packet_hwol_l3_csum_ipv4_ol(b)) {
             dp_packet_ip_set_header_csum(b, false);
         }
     } else if (dp_packet_hwol_tx_l4_checksum(b)) {