2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 06:15:47 +00:00

userspace: Enable tunnel tests with TSO.

This patch enables most of the tunnel tests in the testsuite, and adds a
large TCP transfer to a vxlan and geneve test to verify TSO
functionality. Some additional changes were required to accommodate these
changes with netdev-linux interfaces. The test for vlan over vxlan is
purposely not enabled as the traffic produced by this test gives
incorrect values in the vnet header.

Acked-by: Simon Horman <horms@ovn.org>
Signed-off-by: Mike Pattrick <mkp@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Mike Pattrick
2024-01-17 14:26:31 -05:00
committed by Ilya Maximets
parent 084c808729
commit 85bcbbed83
8 changed files with 225 additions and 95 deletions

View File

@@ -7145,8 +7145,12 @@ netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu)
if (dp_packet_hwol_is_tso(b)) {
uint16_t tso_segsz = dp_packet_get_tso_segsz(b);
struct tcp_header *tcp = dp_packet_l4(b);
struct tcp_header *inner_tcp = dp_packet_inner_l4(b);
if (inner_tcp) {
tcp = inner_tcp;
}
int tcp_hdr_len = TCP_OFFSET(tcp->tcp_ctl) * 4;
int hdr_len = ((char *) dp_packet_l4(b) - (char *) dp_packet_eth(b))
int hdr_len = ((char *) tcp - (char *) dp_packet_eth(b))
+ tcp_hdr_len;
int max_packet_len = mtu + ETH_HEADER_LEN + VLAN_HEADER_LEN;
@@ -7164,17 +7168,35 @@ netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu)
} else if (dp_packet_hwol_tx_ipv6(b)) {
vnet->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
}
} else {
vnet->hdr_len = 0;
vnet->gso_size = 0;
vnet->gso_type = VIRTIO_NET_HDR_GSO_NONE;
}
if (dp_packet_l4_checksum_good(b)) {
bool l4_is_good = dp_packet_l4_checksum_good(b);
if ((dp_packet_hwol_is_tunnel_vxlan(b) ||
dp_packet_hwol_is_tunnel_geneve(b)) &&
dp_packet_hwol_tx_l4_checksum(b)) {
/* This condition is needed because dp-packet doesn't currently track
* outer and inner checksum statuses seperately. In the case of these
* two tunnel types we can end up setting outer l4 as good but still
* need to complete the inner l4. */
l4_is_good = !(dp_packet_hwol_l4_is_tcp(b) ||
dp_packet_hwol_l4_is_udp(b));
}
if (l4_is_good) {
/* 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. */
dp_packet_ip_set_header_csum(b, false);
}
} else if (dp_packet_hwol_tx_l4_checksum(b)) {
/* The csum calculation is offloaded. */
if (dp_packet_hwol_l4_is_tcp(b)) {
@@ -7192,20 +7214,28 @@ netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu)
* the TCP pseudo header, so that replacing it by the ones
* complement checksum of the TCP header and body will give
* the correct result. */
void *l3_off = dp_packet_inner_l3(b);
void *l4_off = dp_packet_inner_l4(b);
struct tcp_header *tcp_hdr = dp_packet_l4(b);
if (!l3_off || !l4_off) {
l3_off = dp_packet_l3(b);
l4_off = dp_packet_l4(b);
}
struct tcp_header *tcp_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 = l3_off;
csum = ~csum_finish(packet_csum_pseudoheader6(ip6_hdr));
}
tcp_hdr->tcp_csum = csum;
vnet->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
vnet->csum_start = (OVS_FORCE __virtio16) b->l4_ofs;
vnet->csum_start = (OVS_FORCE __virtio16) ((char *) l4_off -
(char *) dp_packet_data(b));
vnet->csum_offset = (OVS_FORCE __virtio16) __builtin_offsetof(
struct tcp_header, tcp_csum);
} else if (dp_packet_hwol_l4_is_udp(b)) {
@@ -7222,7 +7252,8 @@ netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu)
udp_hdr->udp_csum = csum;
vnet->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
vnet->csum_start = (OVS_FORCE __virtio16) b->l4_ofs;
vnet->csum_start = (OVS_FORCE __virtio16) ((char *) udp_hdr -
(char *) dp_packet_data(b));;
vnet->csum_offset = (OVS_FORCE __virtio16) __builtin_offsetof(
struct udp_header, udp_csum);
} else if (dp_packet_hwol_l4_is_sctp(b)) {