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.march...@redhat.com> --- Changes since v1: - added check on payload presence in packet, - updated the added test name for consistency, - used helpers for creating bridge and ports in unit tests, - added coverage for segmentation size larger than checked packet length, --- lib/odp-execute.c | 19 +++++++++++++++ tests/dpif-netdev.at | 57 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 649f8e99a5..7f4e337f8a 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -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]; diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at index 6804a9c5c9..d1300ec67d 100644 --- a/tests/dpif-netdev.at +++ b/tests/dpif-netdev.at @@ -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_br 1 +add_of_ports --pcap br1 `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 br1]) +AT_CHECK([ovs-ofctl add-flows br1 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), 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=500]) + +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 \ -- 2.51.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev