diff mbox series

[ipsec,v1,2/2] xfrm: Migrate offload configuration

Message ID 20250122120941.2634198-3-chiachangwang@google.com (mailing list archive)
State Awaiting Upstream
Delegated to: Netdev Maintainers
Headers show
Series Update offload configuration with SA | expand

Checks

Context Check Description
netdev/series_format warning Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 0 this patch: 7
netdev/build_tools success Errors and warnings before: 0 (+1) this patch: 0 (+1)
netdev/cc_maintainers warning 5 maintainers not CCed: herbert@gondor.apana.org.au pabeni@redhat.com edumazet@google.com horms@kernel.org kuba@kernel.org
netdev/build_clang fail Errors and warnings before: 211 this patch: 213
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 227 this patch: 234
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 97 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Chiachang Wang Jan. 22, 2025, 12:09 p.m. UTC
If the SA contains offload configuration, the migration
path should update the SA as well.

This change supports SA migration with the offload attribute
configured. This allows the device to migrate with offload
configuration.

Test: Endable both in/out IPSec crypto offload, and verify
      with Android device on both WiFi/cellular network,
      including:
      1. WiFi + offload -> Cellular + offload
      2. WiFi + offload -> Cellular + no offload
      3. WiFi + no offload -> Cellular + offload
      4. Wifi + no offload -> Cellular + no offload
      5. Cellular + offload -> WiFi + offload
      6. Cellular + no offload -> WiFi + offload
      7. Cellular + offload -> WiFi + no offload
      8. Cell + no offload -> WiFi + no offload
Signed-off-by: Chiachang Wang <chiachangwang@google.com>
---
 include/net/xfrm.h     |  8 ++++++--
 net/xfrm/xfrm_policy.c |  4 ++--
 net/xfrm/xfrm_state.c  | 14 +++++++++++---
 net/xfrm/xfrm_user.c   | 15 +++++++++++++--
 4 files changed, 32 insertions(+), 9 deletions(-)

Comments

Simon Horman Jan. 22, 2025, 1:05 p.m. UTC | #1
On Wed, Jan 22, 2025 at 12:09:41PM +0000, Chiachang Wang wrote:
> If the SA contains offload configuration, the migration
> path should update the SA as well.
> 
> This change supports SA migration with the offload attribute
> configured. This allows the device to migrate with offload
> configuration.
> 
> Test: Endable both in/out IPSec crypto offload, and verify
>       with Android device on both WiFi/cellular network,
>       including:
>       1. WiFi + offload -> Cellular + offload
>       2. WiFi + offload -> Cellular + no offload
>       3. WiFi + no offload -> Cellular + offload
>       4. Wifi + no offload -> Cellular + no offload
>       5. Cellular + offload -> WiFi + offload
>       6. Cellular + no offload -> WiFi + offload
>       7. Cellular + offload -> WiFi + no offload
>       8. Cell + no offload -> WiFi + no offload
> Signed-off-by: Chiachang Wang <chiachangwang@google.com>

...

> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index 46d75980eb2e..2fdb4ea97844 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -2007,22 +2007,30 @@ 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;
> -
> +	bool offload = (xuo);
>  	xc = xfrm_state_clone(x, encap);
>  	if (!xc)
>  		return NULL;
>  
>  	xc->props.family = m->new_family;
>  
> -	if (xfrm_init_state(xc) < 0)
> +	if (__xfrm_init_state(xc, true, offload, NULL) < 0)
>  		goto error;
>  
> +	x->km.state = XFRM_STATE_VALID;
>  	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 (offload & xfrm_dev_state_add(net, xc, xuo, extack))

Hi Chiachang Wang,

This looks like it is intended to be a logical and (&&)
rather than a bitwise and (&).

Flagged by Smatch.

> +		goto error;
> +
>  	/* add state */
>  	if (xfrm_addr_equal(&x->id.daddr, &m->new_daddr, m->new_family)) {
>  		/* a care is needed when the destination address of the
diff mbox series

Patch

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 32c09e85a64c..a1359f912298 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1822,12 +1822,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);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 4408c11c0835..3f5a06f3f0d2 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -4622,7 +4622,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;
@@ -4655,7 +4655,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++;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 46d75980eb2e..2fdb4ea97844 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2007,22 +2007,30 @@  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;
-
+	bool offload = (xuo);
 	xc = xfrm_state_clone(x, encap);
 	if (!xc)
 		return NULL;
 
 	xc->props.family = m->new_family;
 
-	if (xfrm_init_state(xc) < 0)
+	if (__xfrm_init_state(xc, true, offload, NULL) < 0)
 		goto error;
 
+	x->km.state = XFRM_STATE_VALID;
 	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 (offload & 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)) {
 		/* a care is needed when the destination address of the
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index b2876e09328b..505ae2427822 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2989,6 +2989,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]) {
@@ -3019,11 +3020,21 @@  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