From cc9e928f0a12f04c82356c02dd9a84ac6b383fb9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 5 Dec 2023 12:37:50 +0100 Subject: [PATCH] bridge: rework config change pvid handling Fix issues when a member port is moved from one VLAN to another Signed-off-by: Felix Fietkau --- bridge.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/bridge.c b/bridge.c index f400743..2128ec7 100644 --- a/bridge.c +++ b/bridge.c @@ -223,7 +223,9 @@ bridge_set_member_vlan(struct bridge_member *bm, struct bridge_vlan *vlan, bool if (!port) return; - if (bridge_member_vlan_is_pvid(bm, port)) + if (!add && bm->pvid == vlan->vid) + bm->pvid = 0; + else if (add && bridge_member_vlan_is_pvid(bm, port)) bm->pvid = vlan->vid; __bridge_set_member_vlan(bm, vlan, port, add); @@ -275,12 +277,12 @@ bridge_set_vlan_state(struct bridge_state *bst, struct bridge_vlan *vlan, bool a { struct bridge_member *bm; struct bridge_vlan *vlan2; + bool clear_pvid = false; bridge_set_local_vlan(bst, vlan, add); vlist_for_each_element(&bst->members, bm, node) { struct bridge_vlan_port *port; - int new_pvid = -1; port = bridge_find_vlan_member_port(bm, vlan); if (!port) @@ -293,17 +295,18 @@ bridge_set_vlan_state(struct bridge_state *bst, struct bridge_vlan *vlan, bool a vlan2 = bridge_recalc_member_pvid(bm); if (vlan2 && vlan2->vid != vlan->vid) { bridge_set_member_vlan(bm, vlan2, false); + bm->pvid = vlan2->vid; bridge_set_member_vlan(bm, vlan2, true); + } else if (!vlan2) { + clear_pvid = true; } - new_pvid = vlan2 ? vlan2->vid : 0; } - if (!bm->present) - continue; + if (bm->present) + __bridge_set_member_vlan(bm, vlan, port, add); - __bridge_set_member_vlan(bm, vlan, port, add); - if (new_pvid >= 0) - bm->pvid = new_pvid; + if (clear_pvid) + bm->pvid = 0; } } @@ -1369,14 +1372,14 @@ bridge_vlan_update(struct vlist_tree *tree, struct vlist_node *node_new, struct bridge_state *bst = container_of(tree, struct bridge_state, dev.vlans); struct bridge_vlan *vlan_new = NULL, *vlan_old = NULL; - if (!bst->has_vlans || !bst->active) - goto out; - if (node_old) vlan_old = container_of(node_old, struct bridge_vlan, node); if (node_new) vlan_new = container_of(node_new, struct bridge_vlan, node); + if (!bst->has_vlans || !bst->active) + goto out; + if (node_new && node_old && bridge_vlan_equal(vlan_old, vlan_new)) { list_splice_init(&vlan_old->hotplug_ports, &vlan_new->hotplug_ports); goto out; -- 2.30.2