Thread (3 messages) 3 messages, 2 authors, 2d ago

[PATCH net] selftests: openvswitch: Test SET on later IPv6 fragments

flat view
WARM2d

From: Sahaj Chaudhari <hidden>
Date: 2026-10-09 09:05:54
Also in: linux-kselftest
Subsystem: kernel selftest framework, networking [general], openvswitch, the rest · Maintainers: Shuah Khan, Shuah Khan, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Aaron Conole, Eelco Chaudron, Ilya Maximets, Linus Torvalds

Add regression coverage for OVS IPv6 SET actions on later IPv6
fragments. A later fragment has no transport header, so the test sends
a crafted noninitial fragment through a source-address SET flow, checks
that the flow counter advances, and looks for a set_ipv6_addr warning.

This covers the later-fragment case handled by the upstream fix.

Signed-off-by: Sahaj Chaudhari <redacted>

---
 tools/testing/selftests/net/openvswitch/Makefile   |  2 +-
 tools/testing/selftests/net/openvswitch/config     |  1 +
 .../selftests/net/openvswitch/openvswitch.sh       | 43 +++++++++++++++++++
 .../selftests/net/openvswitch/ovs-ipv6-frag.py     | 48 ++++++++++++++++++++++
 4 files changed, 93 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/openvswitch/Makefile b/tools/testing/selftests/net/openvswitch/Makefile
index 3fd1da2ec07d5..b3260cd354419 100644
--- a/tools/testing/selftests/net/openvswitch/Makefile
+++ b/tools/testing/selftests/net/openvswitch/Makefile
@@ -6,7 +6,7 @@ CFLAGS += -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INC
 
 TEST_PROGS := openvswitch.sh
 
-TEST_FILES := ovs-dpctl.py
+TEST_FILES := ovs-dpctl.py ovs-ipv6-frag.py
 
 EXTRA_CLEAN := test_netlink_checks
 
diff --git a/tools/testing/selftests/net/openvswitch/config b/tools/testing/selftests/net/openvswitch/config
index a825e0b5c88e5..b062ebbce0f00 100644
--- a/tools/testing/selftests/net/openvswitch/config
+++ b/tools/testing/selftests/net/openvswitch/config
@@ -3,6 +3,7 @@ CONFIG_INET_DIAG=y
 CONFIG_IP_SCTP=y
 CONFIG_IPV6=y
 CONFIG_NETFILTER=y
+CONFIG_DEBUG_NET=y
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NF_CONNTRACK=m
diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh
index a31f7fb6882dc..b9a4c4bf40672 100755
--- a/tools/testing/selftests/net/openvswitch/openvswitch.sh
+++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh
@@ -31,6 +31,7 @@ tests="
 	dec_ttl					ttl: dec_ttl decrements IP TTL
 	flow_set				flow-set: Flow modify
 	action_set				set: SET action rewrites fields
+	ipv6_later_frag				ipv6-frag: SET on a later IPv6 fragment
 	trunc					trunc: output truncation
 	icmpv6					icmpv6: ICMPv6 echo type match
 	sctp_connect_v4				sctp: SCTP flow key matching
@@ -66,6 +67,11 @@ ovs_wait() {
 	return 1
 }
 
+ovs_flow_has_packets() {
+	python3 "$ovs_base/ovs-dpctl.py" dump-flows "$1" |
+		grep -Eq 'packets:[1-9][0-9]*,'
+}
+
 ovs_base=`pwd`
 sbxs=
 sbx_add () {
@@ -445,6 +451,43 @@ test_action_set() {
 	return 0
 }
 
+test_ipv6_later_frag() {
+	local t="test_ipv6_later_frag"
+	local warning="WARNING:.*set_ipv6_addr"
+	local before after
+
+	if ! dmesg >/dev/null 2>&1; then
+		info "dmesg unavailable - cannot check for kernel warning"
+		return $ksft_skip
+	fi
+
+	before=$(dmesg | grep -c "$warning" || true)
+	if [ "$before" -ne 0 ]; then
+		info "set_ipv6_addr warning already present - skipping"
+		return $ksft_skip
+	fi
+
+	sbx_add "$t" || return 1
+	ovs_add_dp "$t" fragtest || return 1
+	ovs_add_netns_and_veths "$t" fragtest client c0 c1 || return 1
+
+	ovs_add_flow "$t" fragtest \
+		'in_port(1),eth(),eth_type(0x86dd),ipv6(proto=44)' \
+		'set(ipv6(src=2001:db8::99,proto=44)),drop' || return 1
+
+	ip netns exec client python3 "$ovs_base/ovs-ipv6-frag.py" c1 || \
+		return 1
+	ovs_wait ovs_flow_has_packets fragtest || return 1
+
+	after=$(dmesg | grep -c "$warning" || true)
+	if [ "$after" -ne "$before" ]; then
+		info "set_ipv6_addr warning emitted for later IPv6 fragment"
+		return 1
+	fi
+
+	return 0
+}
+
 # trunc test
 # - trunc(14): truncate to ETH_HLEN, strips IP payload, ping fails
 # - trunc(1) and trunc(13): kernel rejects below ETH_HLEN (EINVAL)
diff --git a/tools/testing/selftests/net/openvswitch/ovs-ipv6-frag.py b/tools/testing/selftests/net/openvswitch/ovs-ipv6-frag.py
new file mode 100644
index 0000000000000..869f9d6503ef4
--- /dev/null
+++ b/tools/testing/selftests/net/openvswitch/ovs-ipv6-frag.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+import ipaddress
+import socket
+import struct
+import sys
+
+
+def main():
+    if len(sys.argv) != 2:
+        print(f"Usage: {sys.argv[0]} INTERFACE", file=sys.stderr)
+        return 2
+
+    interface = sys.argv[1]
+    payload = bytes(range(8))
+    # Offset 1 and M=1 make this a noninitial fragment.
+    fragment = struct.pack("!BBHI", socket.IPPROTO_TCP, 0, 0x0009, 1)
+    ipv6 = struct.pack(
+        "!IHBB16s16s",
+        6 << 28,
+        len(fragment) + len(payload),
+        socket.IPPROTO_FRAGMENT,
+        64,
+        ipaddress.IPv6Address("2001:db8::1").packed,
+        ipaddress.IPv6Address("2001:db8::2").packed,
+    )
+    ethernet = struct.pack(
+        "!6s6sH",
+        b"\xff" * 6,
+        bytes.fromhex("020000000001"),
+        0x86DD,
+    )
+    packet = ethernet + ipv6 + fragment + payload
+
+    with socket.socket(
+        socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003)
+    ) as sock:
+        sock.bind((interface, 0))
+        sent = sock.send(packet)
+
+    if sent != len(packet):
+        raise OSError(f"short packet send: {sent} of {len(packet)} bytes")
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help