summaryrefslogtreecommitdiff
path: root/net/bridge/br_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r--net/bridge/br_if.c78
1 files changed, 27 insertions, 51 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 55f47cadb114..4c67a32745f6 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -40,12 +40,21 @@ static int port_cost(struct net_device *dev)
switch (ecmd.base.speed) {
case SPEED_10000:
return 2;
- case SPEED_1000:
+ case SPEED_5000:
+ return 3;
+ case SPEED_2500:
return 4;
+ case SPEED_1000:
+ return 5;
case SPEED_100:
return 19;
case SPEED_10:
return 100;
+ case SPEED_UNKNOWN:
+ return 100;
+ default:
+ if (ecmd.base.speed > SPEED_10000)
+ return 1;
}
}
@@ -157,8 +166,9 @@ void br_manage_promisc(struct net_bridge *br)
* This lets us disable promiscuous mode and write
* this config to hw.
*/
- if (br->auto_cnt == 0 ||
- (br->auto_cnt == 1 && br_auto_port(p)))
+ if ((p->dev->priv_flags & IFF_UNICAST_FLT) &&
+ (br->auto_cnt == 0 ||
+ (br->auto_cnt == 1 && br_auto_port(p))))
br_port_clear_promisc(p);
else
br_port_set_promisc(p);
@@ -253,14 +263,14 @@ static void release_nbp(struct kobject *kobj)
kfree(p);
}
-static void brport_get_ownership(struct kobject *kobj, kuid_t *uid, kgid_t *gid)
+static void brport_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
{
struct net_bridge_port *p = kobj_to_brport(kobj);
net_ns_get_ownership(dev_net(p->dev), uid, gid);
}
-static struct kobj_type brport_ktype = {
+static const struct kobj_type brport_ktype = {
#ifdef CONFIG_SYSFS
.sysfs_ops = &brport_sysfs_ops,
#endif
@@ -274,7 +284,7 @@ static void destroy_nbp(struct net_bridge_port *p)
p->br = NULL;
p->dev = NULL;
- dev_put_track(dev, &p->dev_tracker);
+ netdev_put(dev, &p->dev_tracker);
kobject_put(&p->kobj);
}
@@ -376,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);
@@ -423,7 +434,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
return ERR_PTR(-ENOMEM);
p->br = br;
- dev_hold_track(dev, &p->dev_tracker, GFP_KERNEL);
+ netdev_hold(dev, &p->dev_tracker, GFP_KERNEL);
p->dev = dev;
p->path_cost = port_cost(dev);
p->priority = 0x8000 >> BR_PORT_BITS;
@@ -434,7 +445,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
br_stp_port_timer_init(p);
err = br_multicast_add_port(p);
if (err) {
- dev_put_track(dev, &p->dev_tracker);
+ netdev_put(dev, &p->dev_tracker);
kfree(p);
p = ERR_PTR(err);
}
@@ -515,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 gso_max_size = GSO_MAX_SIZE;
- u16 gso_max_segs = GSO_MAX_SEGS;
- const struct net_bridge_port *p;
-
- list_for_each_entry(p, &br->port_list, list) {
- gso_max_size = min(gso_max_size, p->dev->gso_max_size);
- gso_max_segs = min(gso_max_segs, p->dev->gso_max_segs);
- }
- netif_set_gso_max_size(br->dev, gso_max_size);
- netif_set_gso_max_segs(br->dev, gso_max_segs);
-}
-
/*
* Recomputes features using slave's features
*/
@@ -568,26 +565,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
!is_valid_ether_addr(dev->dev_addr))
return -EINVAL;
- /* Also don't allow bridging of net devices that are DSA masters, since
- * the bridge layer rx_handler prevents the DSA fake ethertype handler
- * to be invoked, so we don't get the chance to strip off and parse the
- * DSA switch tag protocol header (the bridge layer just returns
- * RX_HANDLER_CONSUMED, stopping RX processing for these frames).
- * The only case where that would not be an issue is when bridging can
- * already be offloaded, such as when the DSA master is itself a DSA
- * or plain switchdev port, and is bridged only with other ports from
- * the same hardware device.
- */
- if (netdev_uses_dsa(dev)) {
- list_for_each_entry(p, &br->port_list, list) {
- if (!netdev_port_same_parent_id(dev, p->dev)) {
- NL_SET_ERR_MSG(extack,
- "Cannot do software bridging with a DSA master");
- return -EINVAL;
- }
- }
- }
-
/* No bridging of bridges */
if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) {
NL_SET_ERR_MSG(extack,
@@ -615,7 +592,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
err = dev_set_allmulti(dev, 1);
if (err) {
br_multicast_del_port(p);
- dev_put_track(dev, &p->dev_tracker);
+ netdev_put(dev, &p->dev_tracker);
kfree(p); /* kobject not yet init'd, manually free */
goto err1;
}
@@ -662,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)
@@ -678,7 +653,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
/* Ask for permission to use this MAC address now, even if we
* don't end up choosing it below.
*/
- err = dev_pre_changeaddr_notify(br->dev, dev->dev_addr, extack);
+ err = netif_pre_changeaddr_notify(br->dev, dev->dev_addr,
+ extack);
if (err)
goto err6;
}
@@ -703,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);
@@ -725,7 +702,7 @@ err3:
sysfs_remove_link(br->ifobj, p->dev->name);
err2:
br_multicast_del_port(p);
- dev_put_track(dev, &p->dev_tracker);
+ netdev_put(dev, &p->dev_tracker);
kobject_put(&p->kobj);
dev_set_allmulti(dev, -1);
err1:
@@ -749,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);
@@ -758,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;
}
@@ -770,7 +746,7 @@ void br_port_flags_change(struct net_bridge_port *p, unsigned long mask)
if (mask & BR_AUTO_MASK)
nbp_update_port_count(br);
- if (mask & BR_NEIGH_SUPPRESS)
+ if (mask & (BR_NEIGH_SUPPRESS | BR_NEIGH_VLAN_SUPPRESS))
br_recalculate_neigh_suppress_enabled(br);
}