[PATCH net v2] selftests: openvswitch: Test SET on later IPv6 fragments
flat view
COOLING5d
From: Sahaj Chaudhari <hidden>
Date: 2026-10-12 09:49:23
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
Send the crafted later fragment through OVS_PACKET_CMD_EXECUTE to preserve the unset transport-header path from the report. Set frag=2 in the action key and match DEBUG_NET warnings at the skb header check rather than a potentially inlined helper. Skip when CONFIG_DEBUG_NET cannot be confirmed and enable CONFIG_DEBUG_KERNEL in the OVS fragment. Drop the flow-counter assertion because its SET-action dump relies on broken formatting. Link: https://lore.kernel.org/r/20261009090629.1694991-1-sahaj123.sc@gmail.com (local) Signed-off-by: Sahaj Chaudhari <redacted> --- .../testing/selftests/net/openvswitch/config | 1 + .../selftests/net/openvswitch/openvswitch.sh | 33 ++++++++------- .../selftests/net/openvswitch/ovs-dpctl.py | 40 +++++++++++++++++++ .../net/openvswitch/ovs-ipv6-frag.py | 27 ++++++++----- 4 files changed, 76 insertions(+), 25 deletions(-)
diff --git a/tools/testing/selftests/net/openvswitch/config b/tools/testing/selftests/net/openvswitch/config
index b062ebbce0f0..5cb3c0d395f1 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_KERNEL=y CONFIG_DEBUG_NET=y CONFIG_NET_IPGRE=m CONFIG_NET_IPGRE_DEMUX=m
diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh
index b9a4c4bf4067..394cd45a292d 100755
--- a/tools/testing/selftests/net/openvswitch/openvswitch.sh
+++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh@@ -67,11 +67,6 @@ 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 () {
@@ -453,9 +448,23 @@ test_action_set() { test_ipv6_later_frag() { local t="test_ipv6_later_frag" - local warning="WARNING:.*set_ipv6_addr" + local warning="WARNING:.*include/linux/skbuff\.h:" + local config="" + local config_file="/boot/config-$(uname -r)" local before after + if [ -r /proc/config.gz ] && command -v zcat >/dev/null 2>&1; then + config=$(zcat /proc/config.gz 2>/dev/null | + grep -m1 -E '^(CONFIG_DEBUG_NET=y|# CONFIG_DEBUG_NET is not set)$' || true) + elif [ -r "$config_file" ]; then + config=$(grep -m1 -E '^(CONFIG_DEBUG_NET=y|# CONFIG_DEBUG_NET is not set)$' \ + "$config_file" || true) + fi + if [ "$config" != "CONFIG_DEBUG_NET=y" ]; then + info "CONFIG_DEBUG_NET is disabled or kernel config unavailable - skipping" + return $ksft_skip + fi + if ! dmesg >/dev/null 2>&1; then info "dmesg unavailable - cannot check for kernel warning" return $ksft_skip
@@ -463,25 +472,19 @@ test_ipv6_later_frag() { before=$(dmesg | grep -c "$warning" || true) if [ "$before" -ne 0 ]; then - info "set_ipv6_addr warning already present - skipping" + info "skb transport-header 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 || \ + ovs_sbx "$t" python3 "$ovs_base/ovs-ipv6-frag.py" fragtest || \ 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" + info "skb transport-header warning emitted for later IPv6 fragment" return 1 fi
diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
index 1615843c225e..a653353ec100 100644
--- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py
+++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py@@ -47,6 +47,7 @@ OVS_METER_FAMILY = "ovs_meter" OVS_CT_LIMIT_FAMILY = "ovs_ct_limit" OVS_DATAPATH_VERSION = 2 +OVS_PACKET_VERSION = 1 OVS_DP_CMD_NEW = 1 OVS_DP_CMD_DEL = 2 OVS_DP_CMD_GET = 3
@@ -2218,6 +2219,28 @@ class OvsPacket(GenericNetlinkSocket): GenericNetlinkSocket.__init__(self) self.bind(OVS_PACKET_FAMILY, OvsPacket.ovs_packet_msg) + def execute_packet(self, dpifindex, packet, keystr, actstr): + msg = OvsPacket.ovs_packet_msg() + msg["cmd"] = self.OVS_PACKET_CMD_EXECUTE + msg["version"] = OVS_PACKET_VERSION + msg["reserved"] = 0 + msg["dpifindex"] = dpifindex + + key = ovskey() + key.parse(keystr) + actions = ovsactions() + actions.parse(actstr) + + msg["attrs"].append(["OVS_PACKET_ATTR_PACKET", list(packet)]) + msg["attrs"].append(["OVS_PACKET_ATTR_KEY", key]) + msg["attrs"].append(["OVS_PACKET_ATTR_ACTIONS", actions]) + + return self.nlm_request( + msg, + msg_type=self.prid, + msg_flags=NLM_F_REQUEST | NLM_F_ACK, + ) + def upcall_handler(self, up=None): print("listening on upcall packet handler:", self.epid) while True:
@@ -3010,6 +3033,12 @@ def main(argv): delfscmd = subparsers.add_parser("del-flows") delfscmd.add_argument("flsbr", help="Datapath name") + execcmd = subparsers.add_parser("execute") + execcmd.add_argument("execdp", help="Datapath name") + execcmd.add_argument("execpacket", help="Ethernet packet as hexadecimal") + execcmd.add_argument("execkey", help="Flow key") + execcmd.add_argument("execacts", help="Flow actions") + subparsers.add_parser("psample-events") args = parser.parse_args()
@@ -3088,6 +3117,17 @@ def main(argv): if args.dellink: ipr = pyroute2.iproute.IPRoute() ipr.link("del", index=ipr.link_lookup(ifname=args.delif)[0]) + elif hasattr(args, "execdp"): + rep = ovsdp.info(args.execdp, 0) + if rep is None: + print("DP '%s' not found." % args.execdp) + return 1 + ovspk.execute_packet( + rep["dpifindex"], + bytes.fromhex(args.execpacket), + args.execkey, + args.execacts, + ) elif hasattr(args, "dumpdp"): rep = ovsdp.info(args.dumpdp, 0) if rep is None:
diff --git a/tools/testing/selftests/net/openvswitch/ovs-ipv6-frag.py b/tools/testing/selftests/net/openvswitch/ovs-ipv6-frag.py
index 869f9d6503ef..927676e83314 100644
--- a/tools/testing/selftests/net/openvswitch/ovs-ipv6-frag.py
+++ b/tools/testing/selftests/net/openvswitch/ovs-ipv6-frag.py@@ -2,17 +2,19 @@ # SPDX-License-Identifier: GPL-2.0 import ipaddress +import os import socket import struct +import subprocess import sys def main(): if len(sys.argv) != 2: - print(f"Usage: {sys.argv[0]} INTERFACE", file=sys.stderr) + print(f"Usage: {sys.argv[0]} DATAPATH", file=sys.stderr) return 2 - interface = sys.argv[1] + datapath = 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)
@@ -33,14 +35,19 @@ def main(): ) 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") + ovs_dpctl = os.path.join(os.path.dirname(__file__), "ovs-dpctl.py") + subprocess.run( + [ + sys.executable, + ovs_dpctl, + "execute", + datapath, + packet.hex(), + "eth(),eth_type(0x86dd),ipv6(proto=44)", + "set(ipv6(src=2001:db8::99,proto=44,frag=2)),drop", + ], + check=True, + ) return 0
--
2.43.0