Skip to content

Commit ec13009

Browse files
Jianbo Liukuba-moo
authored andcommitted
bonding: implement xdo_dev_state_free and call it after deletion
Add this implementation for bonding, so hardware resources can be freed from the active slave after xfrm state is deleted. The netdev used to invoke xdo_dev_state_free callback, is saved in the xfrm state (xs->xso.real_dev), which is also the bond's active slave. To prevent it from being freed, acquire netdev reference before leaving RCU read-side critical section, and release it after callback is done. And call it when deleting all SAs from old active real interface while switching current active slave. Fixes: 9a56055 ("bonding: Add struct bond_ipesc to manage SA") Signed-off-by: Jianbo Liu <jianbol@nvidia.com> Signed-off-by: Tariq Toukan <tariqt@nvidia.com> Reviewed-by: Hangbin Liu <liuhangbin@gmail.com> Acked-by: Jay Vosburgh <jv@jvosburgh.net> Link: https://patch.msgid.link/20240823031056.110999-2-jianbol@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 65a3cce commit ec13009

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

drivers/net/bonding/bond_main.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,12 +581,47 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
581581
__func__);
582582
} else {
583583
slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
584+
if (slave->dev->xfrmdev_ops->xdo_dev_state_free)
585+
slave->dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
584586
}
585587
}
586588
spin_unlock_bh(&bond->ipsec_lock);
587589
rcu_read_unlock();
588590
}
589591

592+
static void bond_ipsec_free_sa(struct xfrm_state *xs)
593+
{
594+
struct net_device *bond_dev = xs->xso.dev;
595+
struct net_device *real_dev;
596+
netdevice_tracker tracker;
597+
struct bonding *bond;
598+
struct slave *slave;
599+
600+
if (!bond_dev)
601+
return;
602+
603+
rcu_read_lock();
604+
bond = netdev_priv(bond_dev);
605+
slave = rcu_dereference(bond->curr_active_slave);
606+
real_dev = slave ? slave->dev : NULL;
607+
netdev_hold(real_dev, &tracker, GFP_ATOMIC);
608+
rcu_read_unlock();
609+
610+
if (!slave)
611+
goto out;
612+
613+
if (!xs->xso.real_dev)
614+
goto out;
615+
616+
WARN_ON(xs->xso.real_dev != real_dev);
617+
618+
if (real_dev && real_dev->xfrmdev_ops &&
619+
real_dev->xfrmdev_ops->xdo_dev_state_free)
620+
real_dev->xfrmdev_ops->xdo_dev_state_free(xs);
621+
out:
622+
netdev_put(real_dev, &tracker);
623+
}
624+
590625
/**
591626
* bond_ipsec_offload_ok - can this packet use the xfrm hw offload
592627
* @skb: current data packet
@@ -627,6 +662,7 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
627662
static const struct xfrmdev_ops bond_xfrmdev_ops = {
628663
.xdo_dev_state_add = bond_ipsec_add_sa,
629664
.xdo_dev_state_delete = bond_ipsec_del_sa,
665+
.xdo_dev_state_free = bond_ipsec_free_sa,
630666
.xdo_dev_offload_ok = bond_ipsec_offload_ok,
631667
};
632668
#endif /* CONFIG_XFRM_OFFLOAD */

0 commit comments

Comments
 (0)