diff mbox series

[ipsec,v1,1/2] xfrm: Update offload configuration during SA updates

Message ID 20250122120941.2634198-2-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 success Errors and warnings before: 0 this patch: 0
netdev/build_tools success No tools touched, skip
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 success Errors and warnings before: 2 this patch: 2
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 success Errors and warnings before: 101 this patch: 101
netdev/checkpatch warning WARNING: line length of 81 exceeds 80 columns
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
The offload setting is set to HW when the ipsec session is
initialized but cannot be changed until the session is torn
down. The session administrator should be able to update
the SA via netlink message.

This patch ensures that when a SA is updated, the associated
offload configuration is also updated. This is necessary to
maintain consistency between the SA and the offload device,
especially when the device is configured for IPSec offload.

Any offload changes to the SA are reflected in the kernel
and offload device.

Test: Enable both in/out crypto offload, and verify with
      Android device on WiFi/cellular network, including
      1. WiFi + crypto offload -> WiFi + no offload
      2. WiFi + no offload -> WiFi + crypto offload
      3. Cellular + crypto offload -> Cellular + no offload
      4. Cellular + no offload -> Cellular + crypto offload
Signed-off-by: Chiachang Wang <chiachangwang@google.com>
---
 net/xfrm/xfrm_state.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

Comments

Leon Romanovsky Jan. 22, 2025, 1:07 p.m. UTC | #1
On Wed, Jan 22, 2025 at 12:09:40PM +0000, Chiachang Wang wrote:
> The offload setting is set to HW when the ipsec session is
> initialized but cannot be changed until the session is torn
> down. The session administrator should be able to update
> the SA via netlink message.
> 
> This patch ensures that when a SA is updated, the associated
> offload configuration is also updated. This is necessary to
> maintain consistency between the SA and the offload device,
> especially when the device is configured for IPSec offload.
> 
> Any offload changes to the SA are reflected in the kernel
> and offload device.
> 
> Test: Enable both in/out crypto offload, and verify with
>       Android device on WiFi/cellular network, including
>       1. WiFi + crypto offload -> WiFi + no offload
>       2. WiFi + no offload -> WiFi + crypto offload
>       3. Cellular + crypto offload -> Cellular + no offload
>       4. Cellular + no offload -> Cellular + crypto offload

Can you please provide iproute2/*swan commands here?
I would like to test it too and not rely on rely on vague "Android device"
thing.

> Signed-off-by: Chiachang Wang <chiachangwang@google.com>
> ---
>  net/xfrm/xfrm_state.c | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index 67ca7ac955a3..46d75980eb2e 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -2047,7 +2047,8 @@ int xfrm_state_update(struct xfrm_state *x)
>  	int err;
>  	int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
>  	struct net *net = xs_net(x);
> -
> +	struct xfrm_dev_offload *xso;
> +	struct net_device *old_dev;
>  	to_put = NULL;
>  
>  	spin_lock_bh(&net->xfrm.xfrm_state_lock);
> @@ -2124,7 +2125,28 @@ int xfrm_state_update(struct xfrm_state *x)
>  			__xfrm_state_bump_genids(x1);
>  			spin_unlock_bh(&net->xfrm.xfrm_state_lock);
>  		}
> +#ifdef CONFIG_XFRM_OFFLOAD
> +	x1->type_offload = x->type_offload;
> +
> +	if (memcmp(&x1->xso, &x->xso, sizeof(x1->xso))) {
> +		old_dev = x1->xso.dev;
> +		memcpy(&x1->xso, &x->xso, sizeof(x1->xso));
> +
> +		if (old_dev)
> +			old_dev->xfrmdev_ops->xdo_dev_state_delete(x1);
> +
> +		if (x1->xso.dev) {
> +			xso = &x1->xso;
> +			netdev_hold(xso->dev, &xso->dev_tracker, GFP_ATOMIC);
> +			err = xso->dev->xfrmdev_ops->xdo_dev_state_add(x1, NULL);

You should perform whole delete/free/add cycle. Can we have X with
offload while x1 without offload?

>  
> +			if (err) {
> +				netdev_put(xso->dev, &xso->dev_tracker);
> +				goto fail;

In such case, you deleted offload from x1 and left "broken" system.

> +			}
> +		}
> +	}
> +#endif
>  		err = 0;
>  		x->km.state = XFRM_STATE_DEAD;
>  		__xfrm_state_put(x);
> -- 
> 2.48.1.262.g85cc9f2d1e-goog
> 
>
Simon Horman Jan. 22, 2025, 1:08 p.m. UTC | #2
On Wed, Jan 22, 2025 at 12:09:40PM +0000, Chiachang Wang wrote:
> The offload setting is set to HW when the ipsec session is
> initialized but cannot be changed until the session is torn
> down. The session administrator should be able to update
> the SA via netlink message.
> 
> This patch ensures that when a SA is updated, the associated
> offload configuration is also updated. This is necessary to
> maintain consistency between the SA and the offload device,
> especially when the device is configured for IPSec offload.
> 
> Any offload changes to the SA are reflected in the kernel
> and offload device.
> 
> Test: Enable both in/out crypto offload, and verify with
>       Android device on WiFi/cellular network, including
>       1. WiFi + crypto offload -> WiFi + no offload
>       2. WiFi + no offload -> WiFi + crypto offload
>       3. Cellular + crypto offload -> Cellular + no offload
>       4. Cellular + no offload -> Cellular + crypto offload
> Signed-off-by: Chiachang Wang <chiachangwang@google.com>
> ---
>  net/xfrm/xfrm_state.c | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c

...

> @@ -2124,7 +2125,28 @@ int xfrm_state_update(struct xfrm_state *x)
>  			__xfrm_state_bump_genids(x1);
>  			spin_unlock_bh(&net->xfrm.xfrm_state_lock);
>  		}
> +#ifdef CONFIG_XFRM_OFFLOAD
> +	x1->type_offload = x->type_offload;
> +
> +	if (memcmp(&x1->xso, &x->xso, sizeof(x1->xso))) {
> +		old_dev = x1->xso.dev;
> +		memcpy(&x1->xso, &x->xso, sizeof(x1->xso));
> +
> +		if (old_dev)
> +			old_dev->xfrmdev_ops->xdo_dev_state_delete(x1);
> +
> +		if (x1->xso.dev) {
> +			xso = &x1->xso;
> +			netdev_hold(xso->dev, &xso->dev_tracker, GFP_ATOMIC);
> +			err = xso->dev->xfrmdev_ops->xdo_dev_state_add(x1, NULL);
>  
> +			if (err) {
> +				netdev_put(xso->dev, &xso->dev_tracker);
> +				goto fail;
> +			}
> +		}
> +	}
> +#endif

For consistency, it looks like all of the code above should be indented by
one more tabstop.

>  		err = 0;
>  		x->km.state = XFRM_STATE_DEAD;
>  		__xfrm_state_put(x);
diff mbox series

Patch

diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 67ca7ac955a3..46d75980eb2e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2047,7 +2047,8 @@  int xfrm_state_update(struct xfrm_state *x)
 	int err;
 	int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
 	struct net *net = xs_net(x);
-
+	struct xfrm_dev_offload *xso;
+	struct net_device *old_dev;
 	to_put = NULL;
 
 	spin_lock_bh(&net->xfrm.xfrm_state_lock);
@@ -2124,7 +2125,28 @@  int xfrm_state_update(struct xfrm_state *x)
 			__xfrm_state_bump_genids(x1);
 			spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 		}
+#ifdef CONFIG_XFRM_OFFLOAD
+	x1->type_offload = x->type_offload;
+
+	if (memcmp(&x1->xso, &x->xso, sizeof(x1->xso))) {
+		old_dev = x1->xso.dev;
+		memcpy(&x1->xso, &x->xso, sizeof(x1->xso));
+
+		if (old_dev)
+			old_dev->xfrmdev_ops->xdo_dev_state_delete(x1);
+
+		if (x1->xso.dev) {
+			xso = &x1->xso;
+			netdev_hold(xso->dev, &xso->dev_tracker, GFP_ATOMIC);
+			err = xso->dev->xfrmdev_ops->xdo_dev_state_add(x1, NULL);
 
+			if (err) {
+				netdev_put(xso->dev, &xso->dev_tracker);
+				goto fail;
+			}
+		}
+	}
+#endif
 		err = 0;
 		x->km.state = XFRM_STATE_DEAD;
 		__xfrm_state_put(x);