]> git.feebdaed.xyz Git - 0xmirror/ovs.git/commitdiff
odp-execute: Fix packet length check for TSO packets.
authorDavid Marchand <david.marchand@redhat.com>
Wed, 10 Sep 2025 14:46:36 +0000 (16:46 +0200)
committerIlya Maximets <i.maximets@ovn.org>
Thu, 11 Sep 2025 22:20:34 +0000 (00:20 +0200)
TSO packets were incorrectly treated as too big by the check_pkt_len
action with the userspace datapath.
Adjust the check by looking at the requested segment size.

Fixes: 29cf9c1b3b9c ("userspace: Add TCP Segmentation Offload support")
Reported-at: https://issues.redhat.com/browse/FDP-1631
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
lib/odp-execute.c
tests/dpif-netdev.at

index 649f8e99a5dec4b2e74458d94e0455539f304f84..7f4e337f8aadc3d2e5cacb9425da4cdcfd1aaf6c 100644 (file)
@@ -797,6 +797,25 @@ odp_execute_check_pkt_len(void *dp, struct dp_packet *packet, bool steal,
     uint32_t size = dp_packet_get_send_len(packet)
                     - dp_packet_l2_pad_size(packet);
 
+    if (dp_packet_get_tso_segsz(packet)) {
+        const void *payload;
+        uint32_t segsize;
+
+        if (dp_packet_tunnel(packet)) {
+            payload = dp_packet_get_inner_tcp_payload(packet);
+        } else {
+            payload = dp_packet_get_tcp_payload(packet);
+        }
+        if (payload) {
+            /* Evaluate a segment maximum length for this TSO packet. */
+            segsize = (char *) payload - (char *) dp_packet_data(packet)
+                      + dp_packet_get_tso_segsz(packet);
+            if (segsize < size) {
+                size = segsize;
+            }
+        }
+    }
+
     a = attrs[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN];
     if (size > nl_attr_get_u16(a)) {
         a = attrs[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER];
index 6804a9c5c91e1845c678be8335dce083eafea2b8..10dbbb4c7e2fa77767f99399c5c3ff77da610292 100644 (file)
@@ -2245,6 +2245,63 @@ AT_CHECK_UNQUOTED([ovs-pcap p1.pcap | sort], [0], [dnl
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([userspace offload - tso + check_pkt_len])
+OVS_VSWITCHD_START(
+  [set Open_vSwitch . other_config:userspace-tso-enable=true])
+add_of_ports --pcap br0 $(seq 1 3)
+
+AT_CHECK([ovs-appctl vlog/set netdev_dummy:file:dbg])
+
+AT_DATA([flows.txt], [dnl
+table=0,in_port=1,ip actions=check_pkt_larger(514)->NXM_NX_REG0[[0]],resubmit(,1)
+table=1,ip,reg0=0x0 actions=output:2
+table=1,ip,reg0=0x1 actions=output:3
+])
+AT_CHECK([ovs-ofctl del-flows br0])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+flow_s="in_port(1),eth(src=8a:bf:7e:2f:05:84,dst=0a:8f:39:4f:e0:73),eth_type(0x0800), \
+        ipv4(src=192.168.123.2,dst=192.168.123.1,proto=6,tos=1,ttl=64,frag=no), \
+        tcp(src=54392,dst=5201),tcp_flags(ack)"
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 "${flow_s}"])
+
+AT_CHECK([ovs-appctl dpctl/dump-flows | strip_used | strip_stats], [0], [dnl
+flow-dump from the main thread:
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), dnl
+packets:0, bytes:0, used:never, actions:check_pkt_len(size=514,gt(3),le(2))
+])
+
+AT_CHECK([ovs-pcap p2-tx.pcap | wc -l], [0], [1
+])
+AT_CHECK([ovs-pcap p3-tx.pcap | wc -l], [0], [0
+])
+
+AT_CHECK([ovs-vsctl set Interface p1 options:ol_tso_segsz=460])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 "${flow_s}"])
+AT_CHECK([ovs-pcap p2-tx.pcap | wc -l], [0], [2
+])
+AT_CHECK([ovs-pcap p3-tx.pcap | wc -l], [0], [0
+])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 "${flow_s}" --len 974])
+AT_CHECK([ovs-pcap p2-tx.pcap | wc -l], [0], [4
+])
+AT_CHECK([ovs-pcap p3-tx.pcap | wc -l], [0], [0
+])
+
+AT_CHECK([ovs-vsctl set Interface p1 options:ol_tso_segsz=462])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 "${flow_s}" --len 974])
+AT_CHECK([ovs-pcap p2-tx.pcap | wc -l], [0], [4
+])
+AT_CHECK([ovs-pcap p3-tx.pcap | wc -l], [0], [2
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([dpif-netdev - revalidators handle dp modification fail correctly])
 OVS_VSWITCHD_START(
   [add-port br0 p1 \