From: Jihong Min <hurryman2212@gmail.com>
To: netdev@vger.kernel.org
Cc: Jay Vosburgh <jv@jvosburgh.net>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
Steffen Klassert <steffen.klassert@secunet.com>,
Herbert Xu <herbert@gondor.apana.org.au>,
linux-kernel@vger.kernel.org, Jihong Min <hurryman2212@gmail.com>
Subject: [PATCH RFC net-next 4/4] bonding: handle replicated IPsec SAs across LAG changes
Date: Wed, 20 May 2026 17:10:04 +0900 [thread overview]
Message-ID: <20260520081004.2232091-5-hurryman2212@gmail.com> (raw)
In-Reply-To: <20260520081004.2232091-1-hurryman2212@gmail.com>
Keep replicated bonding IPsec state consistent as the LAG changes. Add
newly usable slaves to existing replicated states, remove only the
departing lower instance on down/remove, and update the usable slave
array before hiding lower handles.
Flush bond-owned XFRM offload state when mode or hash policy leaves the
LAG XFRM eligible configuration. Block new LAG offload adds while
pending replicated states are cleaned up and the XFRM table is flushed.
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
drivers/net/bonding/bond_main.c | 45 ++++++++++++++++++++---
drivers/net/bonding/bond_options.c | 57 ++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 4 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index d81dae5a1902..0243950c2fa6 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3104,6 +3104,18 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
bpf_prog_inc(bond->xdp_prog);
}
+#ifdef CONFIG_XFRM_OFFLOAD
+ if ((bond_dev->wanted_features & BOND_XFRM_FEATURES) &&
+ bond_mode_can_use_lag_xfrm(bond)) {
+ bond_sync_slave_xfrm_features(bond, new_slave);
+ bond->notifier_ctx = true;
+ netdev_compute_master_upper_features(bond->dev, true);
+ bond->notifier_ctx = false;
+ }
+#endif /* CONFIG_XFRM_OFFLOAD */
+
+ bond_ipsec_lag_add_slave(bond, new_slave, extack);
+
/* broadcast mode uses the all_slaves to loop through slaves. */
if (bond_mode_can_use_xmit_hash(bond) ||
BOND_MODE(bond) == BOND_MODE_BROADCAST)
@@ -3222,6 +3234,9 @@ static int __bond_release_one(struct net_device *bond_dev,
}
bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_NOW);
+ if (bond_mode_can_use_xmit_hash(bond) ||
+ BOND_MODE(bond) == BOND_MODE_BROADCAST)
+ bond_update_slave_arr(bond, slave);
bond_sysfs_slave_del(slave);
@@ -3239,8 +3254,10 @@ static int __bond_release_one(struct net_device *bond_dev,
slave_warn(bond_dev, slave_dev, "failed to unload XDP program\n");
}
- /* unregister rx_handler early so bond_handle_frame wouldn't be called
- * for this slave anymore.
+ bond_ipsec_lag_remove_slave(bond, slave_dev);
+
+ /* unregister rx_handler after lower IPsec state is gone so RX cannot
+ * bypass the bond while a bond-owned SA is still installed.
*/
netdev_rx_handler_unregister(slave_dev);
@@ -4758,8 +4775,13 @@ static int bond_slave_netdev_event(unsigned long event,
if (BOND_MODE(bond) == BOND_MODE_8023AD)
bond_3ad_adapter_speed_duplex_changed(slave);
- fallthrough;
- case NETDEV_DOWN:
+ bond_sync_slave_xfrm_features(bond, slave);
+ if (bond_mode_can_use_lag_xfrm(bond)) {
+ bond->notifier_ctx = true;
+ netdev_compute_master_upper_features(bond->dev, true);
+ bond->notifier_ctx = false;
+ }
+ bond_ipsec_lag_add_slave(bond, slave, NULL);
/* Refresh slave-array if applicable!
* If the setup does not use miimon or arpmon (mode-specific!),
* then these events will not cause the slave-array to be
@@ -4771,6 +4793,19 @@ static int bond_slave_netdev_event(unsigned long event,
if (bond_mode_can_use_xmit_hash(bond))
bond_update_slave_arr(bond, NULL);
break;
+ case NETDEV_DOWN:
+ /* Refresh slave-array before deleting IPsec state so no new
+ * TX path picks this slave after its offload handle is hidden.
+ */
+ if (bond_mode_can_use_xmit_hash(bond))
+ bond_update_slave_arr(bond, slave);
+ bond_ipsec_lag_remove_slave(bond, slave_dev);
+ if (bond_mode_can_use_lag_xfrm(bond)) {
+ bond->notifier_ctx = true;
+ netdev_compute_master_upper_features(bond->dev, true);
+ bond->notifier_ctx = false;
+ }
+ break;
case NETDEV_CHANGEMTU:
/* TODO: Should slaves be allowed to
* independently alter their MTU? For
@@ -4809,10 +4844,12 @@ static int bond_slave_netdev_event(unsigned long event,
break;
case NETDEV_FEAT_CHANGE:
if (!bond->notifier_ctx) {
+ bond_sync_slave_xfrm_features(bond, slave);
bond->notifier_ctx = true;
netdev_compute_master_upper_features(bond->dev, true);
bond->notifier_ctx = false;
}
+ bond_ipsec_lag_add_slave(bond, slave, NULL);
break;
case NETDEV_RESEND_IGMP:
/* Propagate to master device */
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 634b42c0d8e9..ee3ffc698d7d 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -17,6 +17,7 @@
#include <net/bonding.h>
#include <net/ndisc.h>
+#include <net/xfrm.h>
static int bond_option_active_slave_set(struct bonding *bond,
const struct bond_opt_value *newval);
@@ -894,6 +895,13 @@ static bool bond_set_xfrm_features(struct bonding *bond)
static int bond_option_mode_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
+#if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
+ bool old_ab_xfrm = BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP;
+ bool old_lag_xfrm = bond_mode_can_use_lag_xfrm(bond);
+ bool new_lag_xfrm;
+ bool flush_lag_xfrm = false;
+#endif
+
if (bond->xdp_prog && !bond_xdp_check(bond, newval->value))
return -EOPNOTSUPP;
@@ -918,8 +926,26 @@ static int bond_option_mode_set(struct bonding *bond,
/* don't cache arp_validate between modes */
bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
+
bond->params.mode = newval->value;
+#if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
+ new_lag_xfrm = bond_mode_can_use_lag_xfrm(bond);
+ if (old_ab_xfrm && new_lag_xfrm)
+ bond->dev->wanted_features &= ~BOND_XFRM_FEATURES;
+ if (old_lag_xfrm && !new_lag_xfrm) {
+ bond_ipsec_lag_begin_flush(bond);
+ flush_lag_xfrm = true;
+ }
+
+ if (flush_lag_xfrm) {
+ if (bond->dev->reg_state == NETREG_REGISTERED)
+ xfrm_dev_state_flush(dev_net(bond->dev), bond->dev,
+ true);
+ bond_ipsec_lag_end_flush(bond);
+ }
+#endif
+
/* When changing mode, the bond device is down, we may reduce
* the bond_bcast_neigh_enabled in bond_close() if broadcast_neighbor
* enabled in 8023ad mode. Therefore, only clear broadcast_neighbor
@@ -1575,12 +1601,43 @@ static int bond_option_fail_over_mac_set(struct bonding *bond,
static int bond_option_xmit_hash_policy_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
+#if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
+ bool old_lag_xfrm = bond_mode_can_use_lag_xfrm(bond);
+ bool new_lag_xfrm;
+ bool flush_lag_xfrm = false;
+#endif
+
if (bond->xdp_prog && !__bond_xdp_check(BOND_MODE(bond), newval->value))
return -EOPNOTSUPP;
netdev_dbg(bond->dev, "Setting xmit hash policy to %s (%llu)\n",
newval->string, newval->value);
+
bond->params.xmit_policy = newval->value;
+#if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
+ new_lag_xfrm = bond_mode_can_use_lag_xfrm(bond);
+ if (old_lag_xfrm && !new_lag_xfrm) {
+ bond_ipsec_lag_begin_flush(bond);
+ flush_lag_xfrm = true;
+ }
+
+ if (flush_lag_xfrm) {
+ if (bond->dev->reg_state == NETREG_REGISTERED)
+ xfrm_dev_state_flush(dev_net(bond->dev), bond->dev,
+ true);
+ bond_ipsec_lag_end_flush(bond);
+ }
+#endif
+
+ if (bond->dev->reg_state == NETREG_REGISTERED) {
+ bool update = false;
+
+ update |= bond_set_xfrm_features(bond);
+
+ if (update)
+ netdev_update_features(bond->dev);
+ }
+
return 0;
}
--
2.53.0
prev parent reply other threads:[~2026-05-20 8:10 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-20 8:10 [PATCH RFC net-next 0/4] bonding: support LAG IPsec offload with replicated SAs Jihong Min
2026-05-20 8:10 ` [PATCH RFC net-next 1/4] xfrm: add a lower-device offload handle resolver Jihong Min
2026-05-20 8:10 ` [PATCH RFC net-next 2/4] bonding: replicate XFRM offload state across LAG slaves Jihong Min
2026-05-20 8:10 ` [PATCH RFC net-next 3/4] bonding: expose user-controlled IPsec features for LAG Jihong Min
2026-05-20 8:10 ` Jihong Min [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260520081004.2232091-5-hurryman2212@gmail.com \
--to=hurryman2212@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=herbert@gondor.apana.org.au \
--cc=horms@kernel.org \
--cc=jv@jvosburgh.net \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=steffen.klassert@secunet.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox