Skip to content

Commit

Permalink
netdev-linux: Only repair IP checksum in IPv4.
Browse files Browse the repository at this point in the history
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: 85bcbbe ("userspace: Enable tunnel tests with TSO.")
Reported-by: David Marchand <[email protected]>
Signed-off-by: Mike Pattrick <[email protected]>
Signed-off-by: 0-day Robot <[email protected]>
  • Loading branch information
mkp-rh authored and ovsrobot committed Feb 15, 2024
1 parent 672444d commit f2bb573
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
18 changes: 17 additions & 1 deletion lib/dp-packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)
Expand Down
9 changes: 5 additions & 4 deletions lib/netdev-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down

0 comments on commit f2bb573

Please sign in to comment.