This patch adds userspace DPDK with rte_flow offload unit tests. It can be run with the 'make check-dpdk-offloads' command; however, it requires a list of VFs that can be used for offloaded ports. More details on how to set this up can be found in the testing.rst file.
Also note that currently not all tests are passing. This is true for both the old and the new offload infrastructure: - datapath - ping over ip6gre L2 tunnel This test appears to be failing because the hardware offload NIC is not properly handling checksum offloads. Specifically, the L4 checksum is not updated, and as a result the kernel drops the packets. - mpls - decap header dp-support - mpls - decap header slow-path These two tests fail due to side traffic: an IPv6 drop rule gets installed in hardware. However, this rule also drops MPLS-encapsulated IPv6 traffic. This appears to be a bug specific to the hardware offload NIC in use. Signed-off-by: Eelco Chaudron <[email protected]> --- v2 changes: - Fixed some typos. --- Documentation/topics/testing.rst | 19 ++ tests/.gitignore | 3 + tests/automake.mk | 24 +++ tests/ofproto-macros.at | 6 +- tests/sendpkt.py | 12 +- tests/system-dpdk-offloads-macros.at | 236 ++++++++++++++++++++++ tests/system-dpdk-offloads-testsuite.at | 28 +++ tests/system-dpdk-offloads.at | 223 ++++++++++++++++++++ tests/system-kmod-macros.at | 5 + tests/system-offloads-testsuite-macros.at | 5 + tests/system-traffic.at | 7 + tests/system-userspace-macros.at | 5 + 12 files changed, 568 insertions(+), 5 deletions(-) create mode 100644 tests/system-dpdk-offloads-macros.at create mode 100644 tests/system-dpdk-offloads-testsuite.at create mode 100644 tests/system-dpdk-offloads.at diff --git a/Documentation/topics/testing.rst b/Documentation/topics/testing.rst index dbeaf2d93..e2f8bb643 100644 --- a/Documentation/topics/testing.rst +++ b/Documentation/topics/testing.rst @@ -363,6 +363,25 @@ manual to figure out how to `Configure hugepages`_. All the features documented under `Unit Tests`_ are available for the DPDK testsuite. +Userspace datapath with DPDK offload +'''''''''''''''''''''''''''''''''''' + +To invoke the userspace datapath tests with DPDK and its rte_flow offload, +the same prerequisites apply as above. In addition, six Virtual Function (VF) +interfaces must be preconfigured and capable of hardware offloading traffic +between each other. + +These six VFs need to be passed as a list of PF PCI addresses with their +corresponding VF indexes in the OVS_DPDK_VF_PCI_ADDRS variable. +For example:: + + OVS_DPDK_VF_PCI_ADDRS="0000:17:00.0,0 0000:17:00.0,1 0000:17:00.0,2 0000:17:00.0,3 0000:17:00.0,4 0000:17:00.0,5" + +To invoke the dpdk offloads testsuite with the userspace datapath, run:: + + make check-dpdk-offloads \ + OVS_DPDK_VF_PCI_ADDRS="0000:17:00.0,0 0000:17:00.0,1 0000:17:00.0,2 0000:17:00.0,3 0000:17:00.0,4 0000:17:00.0,5" + Userspace datapath: Testing and Validation of CPU-specific Optimizations '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/tests/.gitignore b/tests/.gitignore index 3a8c45975..b76025d9a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -32,6 +32,9 @@ /system-offloads-testsuite /system-offloads-testsuite.dir/ /system-offloads-testsuite.log +/system-dpdk-offloads-testsuite +/system-dpdk-offloads-testsuite.dir/ +/system-dpdk-offloads-testsuite.log /test-aes128 /test-atomic /test-bundle diff --git a/tests/automake.mk b/tests/automake.mk index 59f538761..da569b022 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -7,6 +7,7 @@ EXTRA_DIST += \ $(SYSTEM_TSO_TESTSUITE_AT) \ $(SYSTEM_AFXDP_TESTSUITE_AT) \ $(SYSTEM_OFFLOADS_TESTSUITE_AT) \ + $(SYSTEM_DPDK_OFFLOADS_TESTSUITE_AT) \ $(SYSTEM_DPDK_TESTSUITE_AT) \ $(OVSDB_CLUSTER_TESTSUITE_AT) \ $(TESTSUITE) \ @@ -15,6 +16,7 @@ EXTRA_DIST += \ $(SYSTEM_TSO_TESTSUITE) \ $(SYSTEM_AFXDP_TESTSUITE) \ $(SYSTEM_OFFLOADS_TESTSUITE) \ + $(SYSTEM_DPDK_OFFLOADS_TESTSUITE) \ $(SYSTEM_DPDK_TESTSUITE) \ $(OVSDB_CLUSTER_TESTSUITE) \ tests/atlocal.in \ @@ -186,6 +188,13 @@ SYSTEM_OFFLOADS_TESTSUITE_AT = \ tests/system-offloads-testsuite.at \ tests/system-offloads-testsuite-macros.at +SYSTEM_DPDK_OFFLOADS_TESTSUITE_AT = \ + tests/system-common-macros.at \ + tests/system-dpdk-macros.at \ + tests/system-dpdk-offloads.at \ + tests/system-dpdk-offloads-macros.at \ + tests/system-dpdk-offloads-testsuite.at + SYSTEM_DPDK_TESTSUITE_AT = \ tests/system-common-macros.at \ tests/system-dpdk-macros.at \ @@ -202,6 +211,7 @@ SYSTEM_USERSPACE_TESTSUITE = $(srcdir)/tests/system-userspace-testsuite SYSTEM_TSO_TESTSUITE = $(srcdir)/tests/system-tso-testsuite SYSTEM_AFXDP_TESTSUITE = $(srcdir)/tests/system-afxdp-testsuite SYSTEM_OFFLOADS_TESTSUITE = $(srcdir)/tests/system-offloads-testsuite +SYSTEM_DPDK_OFFLOADS_TESTSUITE = $(srcdir)/tests/system-dpdk-offloads-testsuite SYSTEM_DPDK_TESTSUITE = $(srcdir)/tests/system-dpdk-testsuite OVSDB_CLUSTER_TESTSUITE = $(srcdir)/tests/ovsdb-cluster-testsuite DISTCLEANFILES += tests/atconfig tests/atlocal @@ -315,6 +325,12 @@ check-offloads-valgrind: all $(valgrind_wrappers) $(check_DATA) @echo '----------------------------------------------------------------------' @echo 'Valgrind output can be found in tests/system-offloads-testsuite.dir/*/valgrind.*' @echo '----------------------------------------------------------------------' +check-dpdk-offloads-valgrind: all $(valgrind_wrappers) $(check_DATA) + $(SHELL) '$(SYSTEM_DPDK_OFFLOADS_TESTSUITE)' -C tests VALGRIND='$(VALGRIND)' AUTOTEST_PATH='tests/valgrind:$(AUTOTEST_PATH)' -d $(TESTSUITEFLAGS) -j1 + @echo + @echo '----------------------------------------------------------------------' + @echo 'Valgrind output can be found in tests/system-dpdk-offloads-testsuite.dir/*/valgrind.*' + @echo '----------------------------------------------------------------------' check-tso-valgrind: all $(valgrind_wrappers) $(check_DATA) $(SHELL) '$(SYSTEM_TSO_TESTSUITE)' -C tests VALGRIND='$(VALGRIND)' AUTOTEST_PATH='tests/valgrind:$(AUTOTEST_PATH)' -d $(TESTSUITEFLAGS) -j1 @echo @@ -357,6 +373,10 @@ check-offloads: all set $(SHELL) '$(SYSTEM_OFFLOADS_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)'; \ "$$@" $(TESTSUITEFLAGS) -j1 || (test X'$(RECHECK)' = Xyes && "$$@" --recheck) +check-dpdk-offloads: all + set $(SHELL) '$(SYSTEM_DPDK_OFFLOADS_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)'; \ + "$$@" $(TESTSUITEFLAGS) -j1 || (test X'$(RECHECK)' = Xyes && "$$@" --recheck) + check-dpdk: all set $(SHELL) '$(SYSTEM_DPDK_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)'; \ "$$@" $(TESTSUITEFLAGS) -j1 || (test X'$(RECHECK)' = Xyes && "$$@" --recheck) @@ -402,6 +422,10 @@ $(SYSTEM_OFFLOADS_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_OFFLOAD $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o [email protected] [email protected] $(AM_V_at)mv [email protected] $@ +$(SYSTEM_DPDK_OFFLOADS_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_DPDK_OFFLOADS_TESTSUITE_AT) $(COMMON_MACROS_AT) + $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o [email protected] [email protected] + $(AM_V_at)mv [email protected] $@ + $(SYSTEM_DPDK_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_DPDK_TESTSUITE_AT) $(COMMON_MACROS_AT) $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o [email protected] [email protected] $(AM_V_at)mv [email protected] $@ diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at index 8894dd711..dd4f485f6 100644 --- a/tests/ofproto-macros.at +++ b/tests/ofproto-macros.at @@ -9,9 +9,9 @@ s/ duration=[0-9.]*s,// s/ cookie=0x0,// s/ table=0,// s/ n_packets=0,// -s/ n_offload_packets=0,// +s/ n_offload_packets=[0-9]*,// s/ n_bytes=0,// -s/ n_offload_bytes=0,// +s/ n_offload_bytes=[0-9]*,// s/ idle_age=[0-9]*,// s/ hard_age=[0-9]*,// s/dp_hash=0x[0-9a-f]*\//dp_hash=0x0\// @@ -127,7 +127,7 @@ strip_xids () { # Changes all 'used:...' to say 'used:0.0', to make output easier to compare. strip_used () { - sed 's/used:[[0-9]]\.[[0-9]]*/used:0.0/' + sed -E 's/used:[[0-9]]+\.[[0-9]]*/used:0.0/' } # Removes all 'duration=...' to make output easier to compare. diff --git a/tests/sendpkt.py b/tests/sendpkt.py index 7cbea5165..b79db1e3f 100755 --- a/tests/sendpkt.py +++ b/tests/sendpkt.py @@ -36,6 +36,9 @@ parser = OptionParser(usage=usage) parser.add_option("-t", "--type", type="string", dest="packet_type", help="packet type ('eth' is the default PACKET_TYPE)", default="eth") +parser.add_option("-c", "--count", type="int", dest="packet_count", + help="number of packets to send (default: 1)", + default=1) (options, args) = parser.parse_args() @@ -44,9 +47,13 @@ if len(args) < 2: parser.print_help() sys.exit(1) -# validate the "-t" or "--type" option +# validate the options if options.packet_type != "eth": parser.error('invalid argument to "-t"/"--type". Allowed value is "eth".') +if options.packet_count < 1: + parser.error('invalid argument to "-c"/"--count". ' + 'Allowed value must be 1 or higher.') + # Strip '0x' prefixes from hex input, combine into a single string and # convert to bytes. @@ -68,7 +75,8 @@ except socket.error as msg: sys.exit(2) try: - sockfd.send(pkt) + for i in range(options.packet_count): + sockfd.send(pkt) except socket.error as msg: print('unable to send packet! error code: ' + str(msg[0]) + ' : ' + msg[1]) diff --git a/tests/system-dpdk-offloads-macros.at b/tests/system-dpdk-offloads-macros.at new file mode 100644 index 000000000..ff7a6e095 --- /dev/null +++ b/tests/system-dpdk-offloads-macros.at @@ -0,0 +1,236 @@ +AT_COPYRIGHT([Copyright (c) 2025 Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.]) + +# Macro to exclude tests that will fail with dpdk offload enabled. +# We currently have the below tests disabled in system-traffic.at +# for the following reasons: +# +# For dpdk offload_mutex there is no kernel side of the simulated VETH +# interface. Therefore the following tests are disabled, as they assume +# kernel ports exist since they have dependencies on their behavior. +# - 'datapath - netdev offload software fallback' +# +# DPDK offload does not update flow statistics when a hardware offloaded flow +# is removed, which means the statistics are incorrect. Until this changes, +# the following test needs to be disabled: +# - 'datapath - simulated flow action update' +# +# The dpdk offload test cases use VF interfaces, which are Ethernet devices +# with a minimum frame size of 64 bytes. As a result, received packets appear +# larger than expected. Virtual interfaces, however, report the actual size. +# To avoid adding complex counter adjustments in tests that rely on these +# values, we skip them. +# - 'conntrack - ICMP related' +# - 'conntrack - resubmit to ct multiple times' +# - 'conntrack - ICMP related with NAT' +# - 'conntrack - Multiple ICMP traverse' +# +# There is a kernel problem where it will not accept fragmented ICMPv6 packets +# for the same session if they are batched together. Due to DUT-specific +# circumstances, this can occasionally happen for the test below. To avoid +# adding complex detection for this, we simply skip the test. +# - 'conntrack - IPv6 fragmentation + vlan' +# +m4_define([CHECK_NO_DPDK_OFFLOAD], +[ + AT_SKIP_IF([:]) +]) + +# OVS_DPDK_OFFLOAD_PRE_CHECK() +# +# Check prerequisites for DPDK rte_flow tests. Following settings are checked: +# - Existence of at least six VFs and their representors. +# +m4_define([OVS_DPDK_OFFLOAD_PRE_CHECK], [ + OVS_DPDK_PRE_CHECK() + AT_SKIP_IF( + [test "$(printf '%s' "$OVS_DPDK_VF_PCI_ADDRS" | wc -w)" -ne 6]) + + AT_SKIP_IF([! ovs_dpdk_verify_vf_cfg "$OVS_DPDK_VF_PCI_ADDRS"]) +]) + +# OVS_TRAFFIC_VSWITCHD_START([vsctl-args], [vsctl-output], [dbinit-aux-args]) +# +# This is a copy from system-dpdk-macro.at with two small changes: +# 1) Use OVS_DPDK_OFFLOAD_PRE_CHECK() instead of OVS_DPDK_PRE_CHECK(). +# 2) Start with pci enabled for PF devices. +# +m4_define([OVS_TRAFFIC_VSWITCHD_START], + [ + OVS_DPDK_OFFLOAD_PRE_CHECK() + OVS_WAIT_WHILE([ip link show ovs-netdev]) + ALLOW_LIST=$(echo "$OVS_DPDK_VF_PCI_ADDRS" | awk '{ + for (i=1; i<=NF; i++) { + split($i, parts, ","); + addr = parts[1]; + if (addr != "" && !seen[addr]) { + seen[addr] = 1; + if (result == "") + result = "--allow " addr; + else + result = result " --allow " addr; + } + } + print result; + }') + OVS_DPDK_START([$ALLOW_LIST], [--disable-system], + [-- set Open_vSwitch . other_config:hw-offload=true $3]) + dnl Add bridges, ports, etc. + OVS_WAIT_WHILE([ip link show br0]) + AT_CHECK([ovs-vsctl -- _ADD_BR([br0]) -- $1 m4_if([$2], [], [], + [| uuidfilt])], [0], [$2]) +]) + +# OVS_TRAFFIC_VSWITCHD_STOP([ALLOWLIST], [extra_cmds]) +# +# This is a copy from system-dpdk-macro.at adding some dpdk offload specific +# error message exclusion. +# +m4_define([OVS_TRAFFIC_VSWITCHD_STOP], + [OVS_DPDK_STOP_VSWITCHD([dnl +$1";/mlx5_net: Failed to update link status: /d"]) + AT_CHECK([:; $2]) +]) + +# ADD_{VF|VETH}([port], [namespace], [ovs-br], [ip_addr] [mac_addr], [gateway], +# [ip_addr_flags]) +# +# Simulate the ADD_VETH() macro defined in system-common-macros.at, allowing +# us to run the existing system-traffic unit tests without any test-specific +# changes. This is consistent with how DPDK and AF_XDP run the system tests, +# except that we are not using actual veth devices, but VF representer ports. +# +m4_define([ADD_VF], + [ USER_PORT=$1 + case "$USER_PORT" in + client) PORT_NO=0 ;; + server) PORT_NO=1 ;; + *) PORT_NO=${USER_PORT##*[!0-9]} ;; + esac + + AT_CHECK([[[ "$PORT_NO" -ge 0 ]] && [[ "$PORT_NO" -le 6 ]] || return 66]) + PORT_CFG=$(echo $OVS_DPDK_VF_PCI_ADDRS | cut -d' ' -f$((PORT_NO+1))) + PF_PCI=$(ovs_dpdk_get_pci_id "$PORT_CFG") + VF_IDX=$(ovs_dpdk_get_vf_idx "$PORT_CFG") + REP=$(ovs_dpdk_get_representor_netdev $PF_PCI $VF_IDX) + AT_CHECK([test $? -eq 0]) + + AT_CHECK([ip link set $REP name $1]) + AT_CHECK([ip link set $1 netns $2]) + AT_CHECK([ovs-vsctl add-port $3 ovs-$1 -- \ + set interface ovs-$1 external-ids:iface-id="$1" -- \ + set interface ovs-$1 type=dpdk -- \ + set interface ovs-$1 \ + options:dpdk-devargs=$PF_PCI,representor=vf$VF_IDX]) + NS_CHECK_EXEC([$2], [ip addr add $4 dev $1 $7]) + NS_CHECK_EXEC([$2], [ip link set dev $1 up]) + if test -n "$5"; then + NS_CHECK_EXEC([$2], [ip link set dev $1 address $5]) + else + NS_CHECK_EXEC([$2], + [ip link set dev $1 address 02:00:00:00:EC:0$PORT_NO]) + fi + if test -n "$6"; then + NS_CHECK_EXEC([$2], [ip route add default via $6]) + fi + on_exit "ip netns exec $2 ip link set $1 netns 1; \ + ip link property del dev $1 altname $REP; \ + ip link set $1 name $REP" + ] +) +m4_define([ADD_VETH], [ADD_VF($@)]) + +# DUMP_DP_IP_CLEAN_SORTED() +# +# Clean up and sort the ovs-dpctl dump-flow output for comparing. +# +m4_define([DUMP_DP_IP_CLEAN_SORTED], [dnl + grep 'eth_type(0x0800)' \ + | sed -e 's/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/recirc_id(0),//' \ + | strip_used | strip_ptype | sort]) + +OVS_START_SHELL_HELPERS + +# ovs_dpdk_is_valid_pci_vf_addr() +# +# Check if the given PF PCI address and the VF number are valid. +# +ovs_dpdk_is_valid_pci_vf_addr() { + PCI_ID='[[0-9a-fA-F]]{4}:[[0-9a-fA-F]]{2}:[[0-9a-fA-F]]{2}\.[[0-7]]' + echo "$1" | grep -E -q "^$PCI_ID,[[0-9]]+$" && return 0 || return 1 +} + +# ovs_dpdk_get_pci_id() +# +ovs_dpdk_get_pci_id() { + printf '%s\n' "${1%%,*}" +} + +# ovs_dpdk_get_vf_idx() +# +ovs_dpdk_get_vf_idx() { + printf '%s\n' "${1##*,}" +} + +# ovs_dpdk_get_representor_netdev(<PF_PCI>, <VF_INDEX>) +# +# This function tries to find the representor netdev for the given PF's VF. +# +ovs_dpdk_get_representor_netdev() { + PF_PCI=$1 + VF_IDX=$2 + + VF_NET_DIR="/sys/bus/pci/devices/$PF_PCI/virtfn$VF_IDX/net" + + if [[ ! -d "$VF_NET_DIR" ]]; then + echo "ERROR: VF $VF_IDX for PF $PF_PCI does not exist" >&2 + return 1 + fi + + for iface in "$VF_NET_DIR"/*; do + if [[ -e "$iface" ]]; then + basename "$iface" + return 0 + fi + done + + echo "ERROR: No representor netdev found for VF $VF_IDX on PF $PF_PCI" >&2 + return 1 +} + +# ovs_dpdk_verify_vf_cfg() +# +# Verify that the given PF PCI addresses and corresponding VF IDs in +# OVS_DPDK_VF_PCI_ADDRS are valid, exist, and have corresponding +# representor ports. +# +ovs_dpdk_verify_vf_cfg() { + i=0 + + for addr in $1; do + ovs_dpdk_is_valid_pci_vf_addr "$addr" || return 1 + + PCI_ID=$(ovs_dpdk_get_pci_id "$addr") + VF_IDX=$(ovs_dpdk_get_vf_idx "$addr") + + REP=$(ovs_dpdk_get_representor_netdev $PCI_ID $VF_IDX) || return 1 + + echo "ovs-p$i: PF PCI $PCI_ID with VF $VF_IDX has representor $REP" + i=$((i + 1)) + done + + return 0 +} + +OVS_END_SHELL_HELPERS diff --git a/tests/system-dpdk-offloads-testsuite.at b/tests/system-dpdk-offloads-testsuite.at new file mode 100644 index 000000000..c4ef22ce0 --- /dev/null +++ b/tests/system-dpdk-offloads-testsuite.at @@ -0,0 +1,28 @@ +AT_INIT + +AT_COPYRIGHT([Copyright (c) 2025 Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.]) + +m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS]) + +m4_include([tests/ovs-macros.at]) +m4_include([tests/ovsdb-macros.at]) +m4_include([tests/ofproto-macros.at]) +m4_include([tests/system-common-macros.at]) +m4_include([tests/system-userspace-macros.at]) +m4_include([tests/system-dpdk-macros.at]) +m4_include([tests/system-dpdk-offloads-macros.at]) + +m4_include([tests/system-dpdk-offloads.at]) +m4_include([tests/system-traffic.at]) diff --git a/tests/system-dpdk-offloads.at b/tests/system-dpdk-offloads.at new file mode 100644 index 000000000..81ab89b2f --- /dev/null +++ b/tests/system-dpdk-offloads.at @@ -0,0 +1,223 @@ +AT_COPYRIGHT([Copyright (c) 2025 Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.]) + +AT_BANNER([dpdk's rte_flow offload unit tests]) + +AT_SETUP([dpdk offload - ping between two hardware offloaded ports]) +OVS_DPDK_OFFLOAD_PRE_CHECK() +OVS_TRAFFIC_VSWITCHD_START() + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) +ADD_NAMESPACES(at_ns0, at_ns1) +ADD_VF(p0, at_ns0, br0, "10.1.1.1/24") +ADD_VF(p1, at_ns1, br0, "10.1.1.2/24") + +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -W 2 10.1.1.2 \ + | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + +OVS_WAIT_UNTIL_EQUAL( + [ovs-appctl dpctl/dump-flows --names type=dpdk,offloaded \ + | DUMP_DP_IP_CLEAN_SORTED], [dnl +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p1 +in_port(ovs-p1),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p0]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +m4_define([DPDK_OFFLOAD_SIX_PORT_PING_TEST], [dnl + AT_SETUP($1) + OVS_DPDK_OFFLOAD_PRE_CHECK() + OVS_TRAFFIC_VSWITCHD_START($2) + m4_ifval([$2], [CHECK_CPU_DISCOVERED([14])]) + + AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) + AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:max-idle=20000]) + ADD_NAMESPACES(at_ns0, at_ns1, at_ns2, at_ns3, at_ns4, at_ns5) + ADD_VF(p0, at_ns0, br0, "10.1.1.1/24") + ADD_VF(p1, at_ns1, br0, "10.1.1.2/24") + ADD_VF(p2, at_ns2, br0, "10.1.1.3/24") + ADD_VF(p3, at_ns3, br0, "10.1.1.4/24") + ADD_VF(p4, at_ns4, br0, "10.1.1.5/24") + ADD_VF(p5, at_ns5, br0, "10.1.1.6/24") + + for NS in $(seq 0 5); do + START=$((NS + 2)) + for IP in $(seq "$START" 6); do + NS_CHECK_EXEC([at_ns$NS], [ping -q -c 3 -i 0.3 -W 2 10.1.1.$IP \ + | FORMAT_PING], [0], [dnl +3 packets transmitted, 3 received, 0% packet loss, time 0ms +]) + done + done + + OVS_WAIT_UNTIL_EQUAL( + [ovs-appctl dpctl/dump-flows --names type=dpdk,offloaded \ + | DUMP_DP_IP_CLEAN_SORTED], [dnl +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p1 +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p2 +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p3 +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p4 +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p5 +in_port(ovs-p1),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p0 +in_port(ovs-p1),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p2 +in_port(ovs-p1),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p3 +in_port(ovs-p1),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p4 +in_port(ovs-p1),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p5 +in_port(ovs-p2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p0 +in_port(ovs-p2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p1 +in_port(ovs-p2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p3 +in_port(ovs-p2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p4 +in_port(ovs-p2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p5 +in_port(ovs-p3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p0 +in_port(ovs-p3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p1 +in_port(ovs-p3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p2 +in_port(ovs-p3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p4 +in_port(ovs-p3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p5 +in_port(ovs-p4),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p0 +in_port(ovs-p4),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p1 +in_port(ovs-p4),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p2 +in_port(ovs-p4),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p3 +in_port(ovs-p4),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p5 +in_port(ovs-p5),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p0 +in_port(ovs-p5),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p1 +in_port(ovs-p5),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p2 +in_port(ovs-p5),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p3 +in_port(ovs-p5),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:196, used:0.0s, actions:ovs-p4]) + + AT_CHECK([ovs-appctl dpctl/offload-stats-show], [0], [ignore], [ignore]) + AT_CHECK([ovs-appctl dpif-netdev/pmd-rxq-show], [0], [ignore], [ignore]) + + OVS_TRAFFIC_VSWITCHD_STOP + AT_CLEANUP +]) + +DPDK_OFFLOAD_SIX_PORT_PING_TEST( + [dpdk offload - ping between six hardware offloaded ports]) + +DPDK_OFFLOAD_SIX_PORT_PING_TEST( + [dpdk offload - ping with multiple offload threads], + [-- set Open_vSwitch . other_config:pmd-cpu-mask=0x3ffc \ + -- set Open_vSwitch . other_config:n-offload-threads=10]) + +AT_SETUP([dpdk offload - partial offload]) +OVS_DPDK_OFFLOAD_PRE_CHECK() +OVS_TRAFFIC_VSWITCHD_START() + +ADD_NAMESPACES(at_ns1, at_ns2, at_ns3, at_ns4) + +ADD_VETH(p1, at_ns1, br0, "10.1.1.1/24") +ADD_VETH(p2, at_ns2, br0, "10.1.1.2/24") +ADD_VETH(p3, at_ns3, br0, "10.1.1.3/24") +ADD_VETH(p4, at_ns4, br0, "10.1.1.4/24") + +AT_DATA([flows.txt], [dnl +table=0,ipv6, actions=drop +table=0,in_port=2 actions=output:1 +table=0,in_port=1 actions=load:0x1->NXM_NX_REG1[[]],resubmit(,1),load:0x2->NXM_NX_REG1[[]],resubmit(,1) +table=1,in_port=1,reg1=0x1 actions=check_pkt_larger(200)->NXM_NX_REG0[[0]],resubmit(,4) +table=1,in_port=1,reg1=0x2 actions=output:2 +table=4,in_port=1,reg0=0x1 actions=output:3 +table=4,in_port=1,reg0=0x0 actions=output:4 +]) +AT_CHECK([ovs-ofctl --protocols=OpenFlow10 add-flows br0 flows.txt]) + +NS_CHECK_EXEC([at_ns1], [ping -q -c 10 -i 0.1 -W 2 -s 64 10.1.1.2 \ + | FORMAT_PING], [0], [dnl +10 packets transmitted, 10 received, 0% packet loss, time 0ms +], [], [ovs-appctl dpctl/dump-flows; ovs-ofctl dump-flows br0]) + +AT_CHECK([ovs-appctl dpctl/dump-flows type=dpdk,partially-offloaded \ + | grep "check_pkt_len" | DUMP_DP_IP_CLEAN_SORTED], [0], [dnl +in_port(2),eth_type(0x0800),ipv4(frag=no), packets:9, bytes:954, used:0.0s, actions:check_pkt_len(size=200,gt(4),le(5)),3 +]) + +AT_CHECK([test $(ovs-appctl dpif-netdev/pmd-stats-show | \ + awk '/phwol hits:/ {sum += $3} END {print sum}') -ge 8]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + +AT_SETUP([dpdk offload - flow modification non-offload -> offload]) +OVS_DPDK_OFFLOAD_PRE_CHECK() +OVS_TRAFFIC_VSWITCHD_START() + +ADD_NAMESPACES(at_ns0, at_ns1, at_ns2) +ADD_VF(p0, at_ns0, br0, "10.1.1.1/24") +ADD_VF(p1, at_ns1, br0, "10.1.1.2/24") +ADD_VF(p2, at_ns2, br0, "10.1.1.3/24") + +NS_CHECK_EXEC([at_ns0], [sysctl -w net.ipv6.conf.all.disable_ipv6=1], [0], + [ignore]) +NS_CHECK_EXEC([at_ns1], [sysctl -w net.ipv6.conf.all.disable_ipv6=1], [0], + [ignore]) +NS_CHECK_EXEC([at_ns2], [sysctl -w net.ipv6.conf.all.disable_ipv6=1], [0], + [ignore]) + +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) + +m4_define([ICMP_PKT], [m4_join([,], + [eth_src=f0:00:00:01:01:01,eth_dst=f0:00:00:01:01:02,eth_type=0x0800], + [nw_src=10.1.1.1,nw_dst=10.1.1.2], + [nw_proto=1,nw_ttl=64,nw_frag=no], + [icmp_type=8,icmp_code=0])]) + +m4_define([ICMP_PKT_REPLY], [m4_join([,], + [eth_src=f0:00:00:01:01:02,eth_dst=f0:00:00:01:01:01,eth_type=0x0800], + [nw_src=10.1.1.2,nw_dst=10.1.1.1], + [nw_proto=1,nw_ttl=64,nw_frag=no], + [icmp_type=8,icmp_code=0])]) + +# Send a packet in one direction; this should create a non-offloadable +# flow between br0 and ovs-p1. +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 \ + $(ovs-ofctl compose-packet --bare 'ICMP_PKT' '')], [0], [ignore]) + +OVS_WAIT_UNTIL_EQUAL( + [ovs-appctl dpctl/dump-flows --names type=partially-offloaded \ + | grep "f0:00:00:01:01:01" | DUMP_DP_IP_CLEAN_SORTED], [dnl +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:br0,ovs-p1,ovs-p2]) + +# Send the reply packet. A new flow should be inserted in hardware for the +# reverse direction (since the FDB entry for the destination is known). +# However, the revalidator should update the originating flow, causing it to +# be fully offloaded. +NS_CHECK_EXEC([at_ns1], [$PYTHON3 $srcdir/sendpkt.py p1 \ + $(ovs-ofctl compose-packet --bare 'ICMP_PKT_REPLY' '')], [0], [ignore]) + +OVS_WAIT_UNTIL_EQUAL( + [ovs-appctl dpctl/dump-flows --names type=dpdk,offloaded \ + | grep "f0:00:00:01:01:01" | DUMP_DP_IP_CLEAN_SORTED], [dnl +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:ovs-p1 +in_port(ovs-p1),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:ovs-p0]) + +# Send 50 packets in each direction, and verify the packets are handled by +# the hardware rather than by the PMDs. +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py -c 50 p0 \ + $(ovs-ofctl compose-packet --bare 'ICMP_PKT' '')], [0], [ignore]) +NS_CHECK_EXEC([at_ns1], [$PYTHON3 $srcdir/sendpkt.py -c 50 p1 \ + $(ovs-ofctl compose-packet --bare 'ICMP_PKT_REPLY' '')], [0], [ignore]) + +OVS_WAIT_UNTIL_EQUAL( + [ovs-appctl dpctl/dump-flows --names type=dpdk,offloaded \ + | grep "f0:00:00:01:01:01" | DUMP_DP_IP_CLEAN_SORTED], [dnl +in_port(ovs-p0),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:50, bytes:3000, used:0.0s, actions:ovs-p1 +in_port(ovs-p1),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:50, bytes:3000, used:0.0s, actions:ovs-p0]) + +AT_CHECK([test $(ovs-appctl dpif-netdev/pmd-stats-show | \ + awk '/packets received:/ {sum += $3} END {print sum}') -lt 10]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at index 1de0e616b..313cd7c38 100644 --- a/tests/system-kmod-macros.at +++ b/tests/system-kmod-macros.at @@ -264,6 +264,11 @@ m4_define([VSCTL_ADD_DATAPATH_TABLE], # specific regression. m4_define([CHECK_L3L4_CONNTRACK_REASM]) +# CHECK_NO_DPDK_OFFLOAD +# +# The kernel module tests do not use dpdk's rte_flow offload. +m4_define([CHECK_NO_DPDK_OFFLOAD]) + # CHECK_NO_TC_OFFLOAD # # The kernel module tests do not use TC offload. diff --git a/tests/system-offloads-testsuite-macros.at b/tests/system-offloads-testsuite-macros.at index c80538fd6..2ce3f4d6f 100644 --- a/tests/system-offloads-testsuite-macros.at +++ b/tests/system-offloads-testsuite-macros.at @@ -32,6 +32,11 @@ m4_define([OVS_TRAFFIC_VSWITCHD_START], RETIS_CHECK_AND_RUN() ]) +# CHECK_NO_DPDK_OFFLOAD +# +# The kernel module tests do not use dpdk's rte_flow offload. +m4_define([CHECK_NO_DPDK_OFFLOAD]) + # Macro to exclude tests that will fail with TC offload enabled. # We currently have the below tests disabled in system-traffic.at # for the following reasons: diff --git a/tests/system-traffic.at b/tests/system-traffic.at index c7f082fb1..7d37a09e4 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -2456,6 +2456,7 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/WARN/d"]) AT_CLEANUP AT_SETUP([datapath - simulated flow action update]) +CHECK_NO_DPDK_OFFLOAD() OVS_TRAFFIC_VSWITCHD_START() ADD_NAMESPACES(at_ns0, at_ns1) @@ -2520,6 +2521,7 @@ AT_CLEANUP AT_SETUP([datapath - netdev offload software fallback]) AT_SKIP_IF([test $HAVE_NC = no]) +CHECK_NO_DPDK_OFFLOAD() OVS_TRAFFIC_VSWITCHD_START() AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"]) @@ -4520,6 +4522,7 @@ AT_CLEANUP AT_SETUP([conntrack - ICMP related]) AT_SKIP_IF([test $HAVE_NC = no]) +CHECK_NO_DPDK_OFFLOAD() CHECK_CONNTRACK() OVS_TRAFFIC_VSWITCHD_START() @@ -5252,6 +5255,7 @@ OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP AT_SETUP([conntrack - IPv6 fragmentation + vlan]) +CHECK_NO_DPDK_OFFLOAD() CHECK_CONNTRACK() OVS_TRAFFIC_VSWITCHD_START() @@ -5898,6 +5902,7 @@ OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP AT_SETUP([conntrack - resubmit to ct multiple times]) +CHECK_NO_DPDK_OFFLOAD() CHECK_CONNTRACK() OVS_TRAFFIC_VSWITCHD_START( @@ -7717,6 +7722,7 @@ AT_CLEANUP AT_SETUP([conntrack - ICMP related with NAT]) AT_SKIP_IF([test $HAVE_NC = no]) AT_SKIP_IF([test $HAVE_TCPDUMP = no]) +CHECK_NO_DPDK_OFFLOAD() CHECK_CONNTRACK() CHECK_CONNTRACK_NAT() OVS_TRAFFIC_VSWITCHD_START() @@ -9243,6 +9249,7 @@ AT_CLEANUP AT_SETUP([conntrack - Multiple ICMP traverse]) dnl This tracks sending ICMP packets via conntrack multiple times for the dnl same packet +CHECK_NO_DPDK_OFFLOAD() CHECK_CONNTRACK() OVS_TRAFFIC_VSWITCHD_START() OVS_CHECK_CT_CLEAR() diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at index 49b277a08..9961b37da 100644 --- a/tests/system-userspace-macros.at +++ b/tests/system-userspace-macros.at @@ -353,6 +353,11 @@ m4_define([CHECK_L3L4_CONNTRACK_REASM], AT_SKIP_IF([:]) ]) +# CHECK_NO_DPDK_OFFLOAD +# +# Plain userspace tests do not use dpdk's rte_flow offload. +m4_define([CHECK_NO_DPDK_OFFLOAD]) + # CHECK_NO_TC_OFFLOAD # # Userspace tests do not use TC offload. -- 2.50.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
