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 Original line 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)
static struct sk_buff *bond_handle_frame(struct sk_buff *skb)
{
{
	struct net_device *slave_dev;
	struct slave *slave;
	struct net_device *bond_dev;
	struct net_device *bond_dev;


	skb = skb_share_check(skb, GFP_ATOMIC);
	skb = skb_share_check(skb, GFP_ATOMIC);
	if (unlikely(!skb))
	if (unlikely(!skb))
		return NULL;
		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))
	if (unlikely(!bond_dev))
		return skb;
		return skb;


	if (bond_dev->priv_flags & IFF_MASTER_ARPMON)
	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;
		skb->deliver_no_wcard = 1;
		return skb;
		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);
		pr_debug("Error %d calling netdev_set_bond_master\n", res);
		goto err_restore_mac;
		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) {
	if (res) {
		pr_debug("Error %d calling netdev_rx_handler_register\n", res);
		pr_debug("Error %d calling netdev_rx_handler_register\n", res);
		goto err_unset_master;
		goto err_unset_master;
@@ -1916,6 +1918,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)


err_unreg_rxhandler:
err_unreg_rxhandler:
	netdev_rx_handler_unregister(slave_dev);
	netdev_rx_handler_unregister(slave_dev);
	synchronize_net();


err_unset_master:
err_unset_master:
	netdev_set_bond_master(slave_dev, NULL);
	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);
	netdev_rx_handler_unregister(slave_dev);
	synchronize_net();
	netdev_set_bond_master(slave_dev, NULL);
	netdev_set_bond_master(slave_dev, NULL);


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


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


		slave_disable_netpoll(slave);
		slave_disable_netpoll(slave);
+3 −0
Original line number Original line Diff line number Diff line
@@ -266,6 +266,9 @@ struct bonding {
#endif /* CONFIG_DEBUG_FS */
#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
 * Returns NULL if the net_device does not belong to any of the bond's slaves
 *
 *