Merge branch 'Update offload configuration with SA'

Chiachang Wang says:

====================
The current Security Association (SA) offload setting
cannot be modified without removing and re-adding the
SA with the new configuration. Although existing netlink
messages allow SA migration, the offload setting will
be removed after migration.

This patchset enhances SA migration to include updating
the offload setting. This is beneficial for devices that
support IPsec session management.
====================

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
Steffen Klassert 2025-04-18 10:58:23 +02:00
commit 86e530c84c
5 changed files with 37 additions and 16 deletions

View file

@ -1904,12 +1904,16 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
u32 if_id);
struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
struct xfrm_migrate *m,
struct xfrm_encap_tmpl *encap);
struct xfrm_encap_tmpl *encap,
struct net *net,
struct xfrm_user_offload *xuo,
struct netlink_ext_ack *extack);
int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
struct xfrm_migrate *m, int num_bundles,
struct xfrm_kmaddress *k, struct net *net,
struct xfrm_encap_tmpl *encap, u32 if_id,
struct netlink_ext_ack *extack);
struct netlink_ext_ack *extack,
struct xfrm_user_offload *xuo);
#endif
int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);

View file

@ -2630,7 +2630,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
}
return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
kma ? &k : NULL, net, NULL, 0, NULL);
kma ? &k : NULL, net, NULL, 0, NULL, NULL);
out:
return err;

View file

@ -4630,7 +4630,7 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
struct xfrm_migrate *m, int num_migrate,
struct xfrm_kmaddress *k, struct net *net,
struct xfrm_encap_tmpl *encap, u32 if_id,
struct netlink_ext_ack *extack)
struct netlink_ext_ack *extack, struct xfrm_user_offload *xuo)
{
int i, err, nx_cur = 0, nx_new = 0;
struct xfrm_policy *pol = NULL;
@ -4663,7 +4663,7 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
if ((x = xfrm_migrate_state_find(mp, net, if_id))) {
x_cur[nx_cur] = x;
nx_cur++;
xc = xfrm_state_migrate(x, mp, encap);
xc = xfrm_state_migrate(x, mp, encap, net, xuo, extack);
if (xc) {
x_new[nx_new] = xc;
nx_new++;

View file

@ -1958,8 +1958,9 @@ static inline int clone_security(struct xfrm_state *x, struct xfrm_sec_ctx *secu
return 0;
}
static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
struct xfrm_encap_tmpl *encap)
static struct xfrm_state *xfrm_state_clone_and_setup(struct xfrm_state *orig,
struct xfrm_encap_tmpl *encap,
struct xfrm_migrate *m)
{
struct net *net = xs_net(orig);
struct xfrm_state *x = xfrm_state_alloc(net);
@ -2058,6 +2059,11 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
goto error;
}
x->props.family = m->new_family;
memcpy(&x->id.daddr, &m->new_daddr, sizeof(x->id.daddr));
memcpy(&x->props.saddr, &m->new_saddr, sizeof(x->props.saddr));
return x;
error:
@ -2120,21 +2126,23 @@ EXPORT_SYMBOL(xfrm_migrate_state_find);
struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
struct xfrm_migrate *m,
struct xfrm_encap_tmpl *encap)
struct xfrm_encap_tmpl *encap,
struct net *net,
struct xfrm_user_offload *xuo,
struct netlink_ext_ack *extack)
{
struct xfrm_state *xc;
xc = xfrm_state_clone(x, encap);
xc = xfrm_state_clone_and_setup(x, encap, m);
if (!xc)
return NULL;
xc->props.family = m->new_family;
if (xfrm_init_state(xc) < 0)
goto error;
memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr));
memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
/* configure the hardware if offload is requested */
if (xuo && xfrm_dev_state_add(net, xc, xuo, extack))
goto error;
/* add state */
if (xfrm_addr_equal(&x->id.daddr, &m->new_daddr, m->new_family)) {

View file

@ -3069,6 +3069,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
int n = 0;
struct net *net = sock_net(skb->sk);
struct xfrm_encap_tmpl *encap = NULL;
struct xfrm_user_offload *xuo = NULL;
u32 if_id = 0;
if (!attrs[XFRMA_MIGRATE]) {
@ -3099,11 +3100,19 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
if (attrs[XFRMA_IF_ID])
if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
if (attrs[XFRMA_OFFLOAD_DEV]) {
xuo = kmemdup(nla_data(attrs[XFRMA_OFFLOAD_DEV]),
sizeof(*xuo), GFP_KERNEL);
if (!xuo) {
err = -ENOMEM;
goto error;
}
}
err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap,
if_id, extack);
if_id, extack, xuo);
error:
kfree(encap);
kfree(xuo);
return err;
}
#else