Commit 45493d47 authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

bridge: notify enslaved devices of headroom changes

On bridge needed_headroom changes, the enslaved devices are
notified via the ndo_set_rx_headroom method
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 871b642a
...@@ -223,6 +223,31 @@ static void destroy_nbp_rcu(struct rcu_head *head) ...@@ -223,6 +223,31 @@ static void destroy_nbp_rcu(struct rcu_head *head)
destroy_nbp(p); destroy_nbp(p);
} }
static unsigned get_max_headroom(struct net_bridge *br)
{
unsigned max_headroom = 0;
struct net_bridge_port *p;
list_for_each_entry(p, &br->port_list, list) {
unsigned dev_headroom = netdev_get_fwd_headroom(p->dev);
if (dev_headroom > max_headroom)
max_headroom = dev_headroom;
}
return max_headroom;
}
static void update_headroom(struct net_bridge *br, int new_hr)
{
struct net_bridge_port *p;
list_for_each_entry(p, &br->port_list, list)
netdev_set_rx_headroom(p->dev, new_hr);
br->dev->needed_headroom = new_hr;
}
/* Delete port(interface) from bridge is done in two steps. /* Delete port(interface) from bridge is done in two steps.
* via RCU. First step, marks device as down. That deletes * via RCU. First step, marks device as down. That deletes
* all the timers and stops new packets from flowing through. * all the timers and stops new packets from flowing through.
...@@ -248,6 +273,9 @@ static void del_nbp(struct net_bridge_port *p) ...@@ -248,6 +273,9 @@ static void del_nbp(struct net_bridge_port *p)
br_ifinfo_notify(RTM_DELLINK, p); br_ifinfo_notify(RTM_DELLINK, p);
list_del_rcu(&p->list); list_del_rcu(&p->list);
if (netdev_get_fwd_headroom(dev) == br->dev->needed_headroom)
update_headroom(br, get_max_headroom(br));
netdev_reset_rx_headroom(dev);
nbp_vlan_flush(p); nbp_vlan_flush(p);
br_fdb_delete_by_port(br, p, 0, 1); br_fdb_delete_by_port(br, p, 0, 1);
...@@ -438,6 +466,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) ...@@ -438,6 +466,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
{ {
struct net_bridge_port *p; struct net_bridge_port *p;
int err = 0; int err = 0;
unsigned br_hr, dev_hr;
bool changed_addr; bool changed_addr;
/* Don't allow bridging non-ethernet like devices, or DSA-enabled /* Don't allow bridging non-ethernet like devices, or DSA-enabled
...@@ -505,8 +534,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) ...@@ -505,8 +534,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
netdev_update_features(br->dev); netdev_update_features(br->dev);
if (br->dev->needed_headroom < dev->needed_headroom) br_hr = br->dev->needed_headroom;
br->dev->needed_headroom = dev->needed_headroom; dev_hr = netdev_get_fwd_headroom(dev);
if (br_hr < dev_hr)
update_headroom(br, dev_hr);
else
netdev_set_rx_headroom(dev, br_hr);
if (br_fdb_insert(br, p, dev->dev_addr, 0)) if (br_fdb_insert(br, p, dev->dev_addr, 0))
netdev_err(dev, "failed insert local address bridge forwarding table\n"); netdev_err(dev, "failed insert local address bridge forwarding table\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment