mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Gabriel Goller <g.goller@proxmox.com>
To: "David S. Miller" <davem@davemloft.net>,
	 Eric Dumazet <edumazet@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>,
	 Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
	 Boris Sukholitko <boris.sukholitko@broadcom.com>,
	 Aaron Conole <aconole@redhat.com>,
	Eelco Chaudron <echaudro@redhat.com>,
	 Ilya Maximets <i.maximets@ovn.org>,
	Shuah Khan <shuah@kernel.org>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	 dev@openvswitch.org, linux-kselftest@vger.kernel.org,
	 Gabriel Goller <g.goller@proxmox.com>
Subject: [PATCH RFC net 2/3] openvswitch: preserve the L3 header after stacked VLAN pushes
Date: Wed, 11 Nov 2026 18:37:50 +0100	[thread overview]
Message-ID: <20261111-net_restore_the-v1-2-6aaeffa601c9@proxmox.com> (raw)
In-Reply-To: <20261111-net_restore_the-v1-0-6aaeffa601c9@proxmox.com>

A second VLAN push moves network_header to the in-band VLAN header.
Subsequent OVS set actions still expect it to point at IP, so they can
modify the wrong bytes and corrupt the packet.

OVS needs to retain the L3 header immediately after the push. Repairing
it only in validate_xmit_skb() is too late for intervening actions and
would not cover packets without CHECKSUM_PARTIAL. Keep this fix separate
from TX validation because it protects action execution, not just offload
preparation. Conversely, fixing OVS alone does not protect packets tagged
by tc or BPF before transmit.

The generic skb_vlan_push() layout is retained for tc classification.
The OVS push-then-set selftest fails without this fix and passes with it
in QEMU.

Fixes: 938863727076 ("tc: adjust network header after 2nd vlan push")
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 net/openvswitch/actions.c                          |  6 +++-
 .../selftests/net/openvswitch/openvswitch.sh       | 34 ++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 12e339cbf791..bf0bb5e6de2c 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -197,9 +197,10 @@ static int pop_vlan(struct sk_buff *skb, struct sw_flow_key *key)
 static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key,
 		     const struct ovs_action_push_vlan *vlan)
 {
+	bool tag_present = skb_vlan_tag_present(skb);
 	int err;
 
-	if (skb_vlan_tag_present(skb)) {
+	if (tag_present) {
 		invalidate_flow_key(key);
 	} else {
 		key->eth.vlan.tci = vlan->vlan_tci;
@@ -207,6 +208,9 @@ static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key,
 	}
 	err = skb_vlan_push(skb, vlan->vlan_tpid,
 			    ntohs(vlan->vlan_tci) & ~VLAN_CFI_MASK);
+	/* OVS actions and TX offloads expect network_header to stay at L3. */
+	if (!err && tag_present)
+		skb->network_header += VLAN_HLEN;
 	skb_reset_mac_len(skb);
 	return err;
 }
diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh
index 21444657a040..339e3e09e643 100755
--- a/tools/testing/selftests/net/openvswitch/openvswitch.sh
+++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh
@@ -28,6 +28,7 @@ tests="
 	tunnel_metadata				ovs: test extraction of tunnel metadata
 	drop_reason				drop: test drop reasons are emitted
 	pop_vlan				vlan: POP_VLAN action strips tag
+	push_vlan_set				vlan: SET after stacked VLAN pushes
 	dec_ttl					ttl: dec_ttl decrements IP TTL
 	flow_set				flow-set: Flow modify
 	action_set				set: SET action rewrites fields
@@ -1501,6 +1502,39 @@ test_tunnel_metadata() {
 	return 0
 }
 
+test_push_vlan_set() {
+	local sbx="test_push_vlan_set"
+	local actions
+
+	sbx_add "$sbx" || return $?
+	ovs_add_dp "$sbx" vlandp || return 1
+	ovs_add_netns_and_veths "$sbx" vlandp \
+		ns1 veth1 ns1veth 192.0.2.1/24 || return 1
+	ovs_add_netns_and_veths "$sbx" vlandp \
+		ns2 veth2 ns2veth 192.0.2.2/24 || return 1
+
+	ovs_add_flow "$sbx" vlandp \
+		'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
+	ovs_add_flow "$sbx" vlandp \
+		'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
+	ovs_add_flow "$sbx" vlandp \
+		'in_port(2),eth(),eth_type(0x0800),ipv4()' '1' || return 1
+
+	# SET must address the IP header while both VLAN tags are present.
+	# Pop them afterwards so the receiver needs no VLAN configuration.
+	actions='push_vlan(vid=200,pcp=0,tpid=0x8100),'
+	actions+='push_vlan(vid=100,pcp=0,tpid=0x8100),'
+	actions+='set(ipv4(src=192.0.2.1,dst=192.0.2.2,'
+	actions+='proto=1,tos=0,ttl=63,frag=0)),pop_vlan,pop_vlan,2'
+	ovs_add_flow "$sbx" vlandp \
+		'in_port(1),eth(),eth_type(0x0800),ipv4(proto=1),icmp()' \
+		"$actions" || return 1
+	ovs_sbx "$sbx" ip netns exec ns1 ping -c 3 -W 2 \
+		192.0.2.2 || return 1
+
+	return 0
+}
+
 test_pop_vlan() {
 	local sbx="test_pop_vlan"
 	sbx_add "$sbx" || return $?

-- 
2.47.3



  parent reply	other threads:[~2026-11-11 17:38 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11 17:37 [PATCH RFC net 0/3] net: fix stacked VLAN header corruption in TX offloads and OVS Gabriel Goller
2026-11-11 17:37 ` [PATCH RFC net 1/3] net: restore the L3 header before VLAN TX offload checks Gabriel Goller
2026-11-11 17:37 ` Gabriel Goller [this message]
2026-11-11 17:37 ` [PATCH RFC net 3/3] net: test stacked VLAN headers before TX offloads Gabriel Goller
2026-11-11 18:33 ` [PATCH RFC net 0/3] net: fix stacked VLAN header corruption in TX offloads and OVS Ilya Maximets

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261111-net_restore_the-v1-2-6aaeffa601c9@proxmox.com \
    --to=g.goller@proxmox.com \
    --cc=aconole@redhat.com \
    --cc=boris.sukholitko@broadcom.com \
    --cc=davem@davemloft.net \
    --cc=dev@openvswitch.org \
    --cc=echaudro@redhat.com \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=i.maximets@ovn.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=shuah@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®