Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -223,6 +223,31 @@ static void destroy_nbp_rcu(struct rcu_head *head)
	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.
 * via RCU. First step, marks device as down. That deletes
 * all the timers and stops new packets from flowing through.
@@ -248,6 +273,9 @@ static void del_nbp(struct net_bridge_port *p)
	br_ifinfo_notify(RTM_DELLINK, p);

	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);
	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)
{
	struct net_bridge_port *p;
	int err = 0;
	unsigned br_hr, dev_hr;
	bool changed_addr;

	/* 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)

	netdev_update_features(br->dev);

	if (br->dev->needed_headroom < dev->needed_headroom)
		br->dev->needed_headroom = dev->needed_headroom;
	br_hr = br->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))
		netdev_err(dev, "failed insert local address bridge forwarding table\n");