summaryrefslogtreecommitdiff
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_forward.c2
-rw-r--r--net/bridge/br_if.c23
-rw-r--r--net/bridge/br_input.c4
-rw-r--r--net/bridge/br_mst.c10
-rw-r--r--net/bridge/br_multicast.c9
-rw-r--r--net/bridge/br_netlink.c2
-rw-r--r--net/bridge/br_private.h13
7 files changed, 35 insertions, 28 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 870bdf2e082c..dea09096ad0f 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -25,7 +25,7 @@ static inline int should_deliver(const struct net_bridge_port *p,
vg = nbp_vlan_group_rcu(p);
return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
- (br_mst_is_enabled(p->br) || p->state == BR_STATE_FORWARDING) &&
+ (br_mst_is_enabled(p) || p->state == BR_STATE_FORWARDING) &&
br_allowed_egress(vg, skb) && nbp_switchdev_allowed_egress(p, skb) &&
!br_skb_isolated(p, skb);
}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 98c5b9c3145f..4c67a32745f6 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -386,6 +386,7 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
del_nbp(p);
}
+ br_mst_uninit(br);
br_recalculate_neigh_suppress_enabled(br);
br_fdb_delete_by_port(br, NULL, 0, 1);
@@ -525,20 +526,6 @@ void br_mtu_auto_adjust(struct net_bridge *br)
br_opt_toggle(br, BROPT_MTU_SET_BY_USER, false);
}
-static void br_set_gso_limits(struct net_bridge *br)
-{
- unsigned int tso_max_size = TSO_MAX_SIZE;
- const struct net_bridge_port *p;
- u16 tso_max_segs = TSO_MAX_SEGS;
-
- list_for_each_entry(p, &br->port_list, list) {
- tso_max_size = min(tso_max_size, p->dev->tso_max_size);
- tso_max_segs = min(tso_max_segs, p->dev->tso_max_segs);
- }
- netif_set_tso_max_size(br->dev, tso_max_size);
- netif_set_tso_max_segs(br->dev, tso_max_segs);
-}
-
/*
* Recomputes features using slave's features
*/
@@ -652,8 +639,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
netdev_err(dev, "failed to sync bridge static fdb addresses to this port\n");
}
- netdev_update_features(br->dev);
-
br_hr = br->dev->needed_headroom;
dev_hr = netdev_get_fwd_headroom(dev);
if (br_hr < dev_hr)
@@ -694,7 +679,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
br_mtu_auto_adjust(br);
- br_set_gso_limits(br);
+
+ netdev_compute_master_upper_features(br->dev, false);
kobject_uevent(&p->kobj, KOBJ_ADD);
@@ -740,7 +726,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
del_nbp(p);
br_mtu_auto_adjust(br);
- br_set_gso_limits(br);
spin_lock_bh(&br->lock);
changed_addr = br_stp_recalculate_bridge_id(br);
@@ -749,7 +734,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
if (changed_addr)
call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
- netdev_update_features(br->dev);
+ netdev_compute_master_upper_features(br->dev, false);
return 0;
}
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 67b4c905e49a..777fa869c1a1 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -94,7 +94,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
br = p->br;
- if (br_mst_is_enabled(br)) {
+ if (br_mst_is_enabled(p)) {
state = BR_STATE_FORWARDING;
} else {
if (p->state == BR_STATE_DISABLED) {
@@ -429,7 +429,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
return RX_HANDLER_PASS;
forward:
- if (br_mst_is_enabled(p->br))
+ if (br_mst_is_enabled(p))
goto defer_stp_filtering;
switch (p->state) {
diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c
index 3f24b4ee49c2..43a300ae6bfa 100644
--- a/net/bridge/br_mst.c
+++ b/net/bridge/br_mst.c
@@ -22,6 +22,12 @@ bool br_mst_enabled(const struct net_device *dev)
}
EXPORT_SYMBOL_GPL(br_mst_enabled);
+void br_mst_uninit(struct net_bridge *br)
+{
+ if (br_opt_get(br, BROPT_MST_ENABLED))
+ static_branch_dec(&br_mst_used);
+}
+
int br_mst_get_info(const struct net_device *dev, u16 msti, unsigned long *vids)
{
const struct net_bridge_vlan_group *vg;
@@ -225,9 +231,9 @@ int br_mst_set_enabled(struct net_bridge *br, bool on,
return err;
if (on)
- static_branch_enable(&br_mst_used);
+ static_branch_inc(&br_mst_used);
else
- static_branch_disable(&br_mst_used);
+ static_branch_dec(&br_mst_used);
br_opt_toggle(br, BROPT_MST_ENABLED, on);
return 0;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 22d12e545966..d55a4ab87837 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -4649,6 +4649,14 @@ static void br_multicast_start_querier(struct net_bridge_mcast *brmctx,
rcu_read_unlock();
}
+static void br_multicast_del_grps(struct net_bridge *br)
+{
+ struct net_bridge_port *port;
+
+ list_for_each_entry(port, &br->port_list, list)
+ __br_multicast_disable_port_ctx(&port->multicast_ctx);
+}
+
int br_multicast_toggle(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack)
{
@@ -4669,6 +4677,7 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val,
br_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val);
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) {
change_snoopers = true;
+ br_multicast_del_grps(br);
goto unlock;
}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 4e2d53b27221..0264730938f4 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -467,7 +467,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
else
br = netdev_priv(dev);
- br_debug(br, "br_fill_info event %d port %s master %s\n",
+ br_debug(br, "br_fill_ifinfo event %d port %s master %s\n",
event, dev->name, br->dev->name);
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 16be5d250402..7280c4e9305f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1935,10 +1935,12 @@ static inline bool br_vlan_state_allowed(u8 state, bool learn_allow)
/* br_mst.c */
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
DECLARE_STATIC_KEY_FALSE(br_mst_used);
-static inline bool br_mst_is_enabled(struct net_bridge *br)
+static inline bool br_mst_is_enabled(const struct net_bridge_port *p)
{
+ /* check the port's vlan group to avoid racing with port deletion */
return static_branch_unlikely(&br_mst_used) &&
- br_opt_get(br, BROPT_MST_ENABLED);
+ br_opt_get(p->br, BROPT_MST_ENABLED) &&
+ rcu_access_pointer(p->vlgrp);
}
int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
@@ -1952,8 +1954,9 @@ int br_mst_fill_info(struct sk_buff *skb,
const struct net_bridge_vlan_group *vg);
int br_mst_process(struct net_bridge_port *p, const struct nlattr *mst_attr,
struct netlink_ext_ack *extack);
+void br_mst_uninit(struct net_bridge *br);
#else
-static inline bool br_mst_is_enabled(struct net_bridge *br)
+static inline bool br_mst_is_enabled(const struct net_bridge_port *p)
{
return false;
}
@@ -1987,6 +1990,10 @@ static inline int br_mst_process(struct net_bridge_port *p,
{
return -EOPNOTSUPP;
}
+
+static inline void br_mst_uninit(struct net_bridge *br)
+{
+}
#endif
struct nf_br_ops {