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

Commit f1c1775a authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

bonding: register slave pointer for rx_handler



Register slave pointer as rx_handler data. That would eventually prevent
need to loop over slave devices to find the right slave.

Use synchronize_net to ensure that bond_handle_frame does not get slave
structure freed when working with that.

Signed-off-by: default avatarJiri Pirko <jpirko@redhat.com>
Reviewed-by: default avatarNicolas de Pesloüan <nicolas.2p.debian@free.fr>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c888385a
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -1482,21 +1482,22 @@ static bool bond_should_deliver_exact_match(struct sk_buff *skb,

static struct sk_buff *bond_handle_frame(struct sk_buff *skb)
{
	struct net_device *slave_dev;
	struct slave *slave;
	struct net_device *bond_dev;

	skb = skb_share_check(skb, GFP_ATOMIC);
	if (unlikely(!skb))
		return NULL;
	slave_dev = skb->dev;
	bond_dev = ACCESS_ONCE(slave_dev->master);

	slave = bond_slave_get_rcu(skb->dev);
	bond_dev = ACCESS_ONCE(slave->dev->master);
	if (unlikely(!bond_dev))
		return skb;

	if (bond_dev->priv_flags & IFF_MASTER_ARPMON)
		slave_dev->last_rx = jiffies;
		slave->dev->last_rx = jiffies;

	if (bond_should_deliver_exact_match(skb, slave_dev, bond_dev)) {
	if (bond_should_deliver_exact_match(skb, slave->dev, bond_dev)) {
		skb->deliver_no_wcard = 1;
		return skb;
	}
@@ -1694,7 +1695,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
		pr_debug("Error %d calling netdev_set_bond_master\n", res);
		goto err_restore_mac;
	}
	res = netdev_rx_handler_register(slave_dev, bond_handle_frame, NULL);
	res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
					 new_slave);
	if (res) {
		pr_debug("Error %d calling netdev_rx_handler_register\n", res);
		goto err_unset_master;
@@ -1916,6 +1918,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)

err_unreg_rxhandler:
	netdev_rx_handler_unregister(slave_dev);
	synchronize_net();

err_unset_master:
	netdev_set_bond_master(slave_dev, NULL);
@@ -2099,6 +2102,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
	}

	netdev_rx_handler_unregister(slave_dev);
	synchronize_net();
	netdev_set_bond_master(slave_dev, NULL);

	slave_disable_netpoll(slave);
@@ -2213,6 +2217,7 @@ static int bond_release_all(struct net_device *bond_dev)
		}

		netdev_rx_handler_unregister(slave_dev);
		synchronize_net();
		netdev_set_bond_master(slave_dev, NULL);

		slave_disable_netpoll(slave);
+3 −0
Original line number Diff line number Diff line
@@ -266,6 +266,9 @@ struct bonding {
#endif /* CONFIG_DEBUG_FS */
};

#define bond_slave_get_rcu(dev) \
	((struct slave *) rcu_dereference(dev->rx_handler_data))

/**
 * Returns NULL if the net_device does not belong to any of the bond's slaves
 *