diff options
author | Jiri Pirko <jiri@resnulli.us> | 2014-09-05 15:51:28 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-09 11:29:54 -0700 |
commit | 0f49579a39533bf839b2af807b094fc652f9e49b (patch) | |
tree | 2f3e7d978d92767ec7f3894f52f714ce7f8ab92f /net/bridge | |
parent | 49a601589caaf0e93194c0cc9b4ecddbe75dd2d5 (diff) | |
download | op-kernel-dev-0f49579a39533bf839b2af807b094fc652f9e49b.zip op-kernel-dev-0f49579a39533bf839b2af807b094fc652f9e49b.tar.gz |
bridge: switch order of rx_handler reg and upper dev link
The thing is that netdev_master_upper_dev_link calls
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev). That generates rtnl
link message and during that, rtnl_link_ops->fill_slave_info is called.
But with current ordering, rx_handler and IFF_BRIDGE_PORT are not set
yet so there would have to be check for that in fill_slave_info callback.
Resolve this by reordering to similar what bonding and team does to
avoid the check.
Also add removal of IFF_BRIDGE_PORT flag into error path.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_if.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 078d336..a9f54a9 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -252,12 +252,12 @@ static void del_nbp(struct net_bridge_port *p) br_fdb_delete_by_port(br, p, 1); nbp_update_port_count(br); + netdev_upper_dev_unlink(dev, br->dev); + dev->priv_flags &= ~IFF_BRIDGE_PORT; netdev_rx_handler_unregister(dev); - netdev_upper_dev_unlink(dev, br->dev); - br_multicast_del_port(p); kobject_uevent(&p->kobj, KOBJ_REMOVE); @@ -476,16 +476,16 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (err) goto err3; - err = netdev_master_upper_dev_link(dev, br->dev); + err = netdev_rx_handler_register(dev, br_handle_frame, p); if (err) goto err4; - err = netdev_rx_handler_register(dev, br_handle_frame, p); + dev->priv_flags |= IFF_BRIDGE_PORT; + + err = netdev_master_upper_dev_link(dev, br->dev); if (err) goto err5; - dev->priv_flags |= IFF_BRIDGE_PORT; - dev_disable_lro(dev); list_add_rcu(&p->list, &br->port_list); @@ -520,7 +520,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) return 0; err5: - netdev_upper_dev_unlink(dev, br->dev); + dev->priv_flags &= ~IFF_BRIDGE_PORT; + netdev_rx_handler_unregister(dev); err4: br_netpoll_disable(p); err3: |