summaryrefslogtreecommitdiff
path: root/net/bridge/br_stp_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_stp_if.c')
-rw-r--r--net/bridge/br_stp_if.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 808e2b914015..c20a41bf253b 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Spanning tree protocol; interface code
* Linux ethernet bridge
*
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
@@ -85,9 +81,9 @@ void br_stp_disable_bridge(struct net_bridge *br)
br->topology_change_detected = 0;
spin_unlock_bh(&br->lock);
- del_timer_sync(&br->hello_timer);
- del_timer_sync(&br->topology_change_timer);
- del_timer_sync(&br->tcn_timer);
+ timer_delete_sync(&br->hello_timer);
+ timer_delete_sync(&br->topology_change_timer);
+ timer_delete_sync(&br->tcn_timer);
cancel_delayed_work_sync(&br->gc_work);
}
@@ -113,11 +109,12 @@ void br_stp_disable_port(struct net_bridge_port *p)
br_ifinfo_notify(RTM_NEWLINK, NULL, p);
- del_timer(&p->message_age_timer);
- del_timer(&p->forward_delay_timer);
- del_timer(&p->hold_timer);
+ timer_delete(&p->message_age_timer);
+ timer_delete(&p->forward_delay_timer);
+ timer_delete(&p->hold_timer);
- br_fdb_delete_by_port(br, p, 0, 0);
+ if (!rcu_access_pointer(p->backup_port))
+ br_fdb_delete_by_port(br, p, 0, 0);
br_multicast_disable_port(p);
br_configuration_update(br);
@@ -199,10 +196,17 @@ static void br_stp_stop(struct net_bridge *br)
br->stp_enabled = BR_NO_STP;
}
-void br_stp_set_enabled(struct net_bridge *br, unsigned long val)
+int br_stp_set_enabled(struct net_bridge *br, unsigned long val,
+ struct netlink_ext_ack *extack)
{
ASSERT_RTNL();
+ if (br_mrp_enabled(br)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "STP can't be enabled if MRP is already enabled");
+ return -EINVAL;
+ }
+
if (val) {
if (br->stp_enabled == BR_NO_STP)
br_stp_start(br);
@@ -210,6 +214,8 @@ void br_stp_set_enabled(struct net_bridge *br, unsigned long val)
if (br->stp_enabled != BR_NO_STP)
br_stp_stop(br);
}
+
+ return 0;
}
/* called under bridge lock */
@@ -227,7 +233,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
memcpy(br->bridge_id.addr, addr, ETH_ALEN);
- memcpy(br->dev->dev_addr, addr, ETH_ALEN);
+ eth_hw_addr_set(br->dev, addr);
list_for_each_entry(p, &br->port_list, list) {
if (ether_addr_equal(p->designated_bridge.addr, oldaddr))