diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2adf6ce20a38..e2d491c4378c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -383,9 +383,14 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, static int bond_ipsec_add_sa(struct xfrm_state *xs) { struct net_device *bond_dev = xs->xso.dev; - struct bonding *bond = netdev_priv(bond_dev); - struct slave *slave = rtnl_dereference(bond->curr_active_slave); + struct bonding *bond; + struct slave *slave; + if (!bond_dev) + return -EINVAL; + + bond = netdev_priv(bond_dev); + slave = rcu_dereference(bond->curr_active_slave); xs->xso.real_dev = slave->dev; bond->xs = xs; @@ -405,8 +410,14 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs) static void bond_ipsec_del_sa(struct xfrm_state *xs) { struct net_device *bond_dev = xs->xso.dev; - struct bonding *bond = netdev_priv(bond_dev); - struct slave *slave = rtnl_dereference(bond->curr_active_slave); + struct bonding *bond; + struct slave *slave; + + if (!bond_dev) + return; + + bond = netdev_priv(bond_dev); + slave = rcu_dereference(bond->curr_active_slave); if (!slave) return; @@ -431,7 +442,7 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs) { struct net_device *bond_dev = xs->xso.dev; struct bonding *bond = netdev_priv(bond_dev); - struct slave *curr_active = rtnl_dereference(bond->curr_active_slave); + struct slave *curr_active = rcu_dereference(bond->curr_active_slave); struct net_device *slave_dev = curr_active->dev; if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) @@ -960,12 +971,12 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) if (old_active == new_active) return; - if (new_active) { #ifdef CONFIG_XFRM_OFFLOAD - if ((BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) && bond->xs) - bond_ipsec_del_sa(bond->xs); + if (old_active && bond->xs) + bond_ipsec_del_sa(bond->xs); #endif /* CONFIG_XFRM_OFFLOAD */ + if (new_active) { new_active->last_link_up = jiffies; if (new_active->link == BOND_LINK_BACK) { @@ -1028,13 +1039,6 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) bond_should_notify_peers(bond); } -#ifdef CONFIG_XFRM_OFFLOAD - if (old_active && bond->xs) { - xfrm_dev_state_flush(dev_net(bond->dev), bond->dev, true); - bond_ipsec_add_sa(bond->xs); - } -#endif /* CONFIG_XFRM_OFFLOAD */ - call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev); if (should_notify_peers) { bond->send_peer_notif--; @@ -1044,6 +1048,13 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) } } +#ifdef CONFIG_XFRM_OFFLOAD + if (new_active && bond->xs) { + xfrm_dev_state_flush(dev_net(bond->dev), bond->dev, true); + bond_ipsec_add_sa(bond->xs); + } +#endif /* CONFIG_XFRM_OFFLOAD */ + /* resend IGMP joins since active slave has changed or * all were sent on curr_active_slave. * resend only if bond is brought up with the affected |