From e35afd3736bb16633fca6ddfbd1537f995c35af0 Mon Sep 17 00:00:00 2001 From: Quinn O'Shea Date: Wed, 30 Sep 2026 20:09:42 -0500 Subject: [PATCH] realtek: pass bridge VLAN protocol changes to DSA drivers DSA ignores SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL, so a bridge that changes its VLAN protocol while switch ports are offloaded keeps them running the old one without telling the driver. Carry a kernel patch that adds an optional port_vlan_protocol operation for that attribute; drivers without it behave as before. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Quinn O'Shea Link: https://github.com/openwrt/openwrt/pull/25927 Signed-off-by: Markus Stockhausen --- ...dge-VLAN-protocol-changes-to-drivers.patch | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 target/linux/realtek/patches-6.18/824-net-dsa-pass-bridge-VLAN-protocol-changes-to-drivers.patch diff --git a/target/linux/realtek/patches-6.18/824-net-dsa-pass-bridge-VLAN-protocol-changes-to-drivers.patch b/target/linux/realtek/patches-6.18/824-net-dsa-pass-bridge-VLAN-protocol-changes-to-drivers.patch new file mode 100644 index 00000000000..b2950a59e40 --- /dev/null +++ b/target/linux/realtek/patches-6.18/824-net-dsa-pass-bridge-VLAN-protocol-changes-to-drivers.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Quinn O'Shea +Date: Wed, 30 Sep 2026 20:09:42 -0500 +Subject: net: dsa: pass bridge VLAN protocol changes to drivers + +A bridge announces a change of its VLAN protocol with +SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL, but DSA has no handler for it and +returns -EOPNOTSUPP, which the bridge takes as acceptance. A switch whose +ports are already offloaded keeps classifying and tagging with the old +TPID while the bridge runs the new protocol. + +Add an optional port_vlan_protocol operation and call it for that +attribute, so a driver can follow the change or refuse it. Drivers that +do not implement it behave as before. + +Signed-off-by: Quinn O'Shea +--- +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -1070,6 +1070,8 @@ struct dsa_switch_ops { + int (*port_vlan_filtering)(struct dsa_switch *ds, int port, + bool vlan_filtering, + struct netlink_ext_ack *extack); ++ int (*port_vlan_protocol)(struct dsa_switch *ds, int port, u16 proto, ++ struct netlink_ext_ack *extack); + int (*port_vlan_add)(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack); +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -872,6 +872,17 @@ bool dsa_port_skip_vlan_configuration(st + return !ds->configure_vlan_while_not_filtering && !br_vlan_enabled(br); + } + ++int dsa_port_vlan_protocol(struct dsa_port *dp, u16 proto, ++ struct netlink_ext_ack *extack) ++{ ++ struct dsa_switch *ds = dp->ds; ++ ++ if (!ds->ops->port_vlan_protocol) ++ return -EOPNOTSUPP; ++ ++ return ds->ops->port_vlan_protocol(ds, dp->index, proto, extack); ++} ++ + int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock) + { + unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock); +--- a/net/dsa/port.h ++++ b/net/dsa/port.h +@@ -39,6 +39,8 @@ void dsa_port_pre_lag_leave(struct dsa_p + void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev); + int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, + struct netlink_ext_ack *extack); ++int dsa_port_vlan_protocol(struct dsa_port *dp, u16 proto, ++ struct netlink_ext_ack *extack); + bool dsa_port_skip_vlan_configuration(struct dsa_port *dp); + int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock); + int dsa_port_mst_enable(struct dsa_port *dp, bool on, +--- a/net/dsa/user.c ++++ b/net/dsa/user.c +@@ -612,6 +612,12 @@ static int dsa_user_port_attr_set(struct + ret = dsa_port_vlan_filtering(dp, attr->u.vlan_filtering, + extack); + break; ++ case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL: ++ if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) ++ return -EOPNOTSUPP; ++ ++ ret = dsa_port_vlan_protocol(dp, attr->u.vlan_protocol, extack); ++ break; + case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: + if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) + return -EOPNOTSUPP;