Skip to content

Commit

Permalink
netdev-linux: Favour inner packet for multi-encapsulated TSO.
Browse files Browse the repository at this point in the history
Previously if an OVS configuration nested multiple layers of UDP tunnels
like VXLAN or GENEVE on top of each other through netdev-linux
interfaces, the vnet header would be incorrectly set to the outermost
UDP tunnel layer instead of the intermediary tunnel layer.

This resulted in the middle UDP tunnel not checksum offloading properly.

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 3e666ba commit 672444d
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions lib/netdev-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -7247,14 +7247,23 @@ netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu)
vnet->csum_offset = (OVS_FORCE __virtio16) __builtin_offsetof(
struct tcp_header, tcp_csum);
} else if (dp_packet_hwol_l4_is_udp(b)) {
struct udp_header *udp_hdr = dp_packet_l4(b);
/* Favour the inner packet when indicating checksum offsets. */
void *l3_off = dp_packet_inner_l3(b);
void *l4_off = dp_packet_inner_l4(b);

if (!l3_off || !l4_off) {
l3_off = dp_packet_l3(b);
l4_off = dp_packet_l4(b);
}
struct udp_header *udp_hdr = l4_off;

ovs_be16 csum = 0;

if (dp_packet_hwol_is_ipv4(b)) {
const struct ip_header *ip_hdr = dp_packet_l3(b);
const struct ip_header *ip_hdr = l3_off;
csum = ~csum_finish(packet_csum_pseudoheader(ip_hdr));
} else if (dp_packet_hwol_tx_ipv6(b)) {
const struct ovs_16aligned_ip6_hdr *ip6_hdr = dp_packet_l3(b);
const struct ovs_16aligned_ip6_hdr *ip6_hdr = l4_off;
csum = ~csum_finish(packet_csum_pseudoheader6(ip6_hdr));
}

Expand Down

0 comments on commit 672444d

Please sign in to comment.