xfrm: allow state packet offload mode
authorLeon Romanovsky <leonro@nvidia.com>
Fri, 2 Dec 2022 18:41:28 +0000 (20:41 +0200)
committerSteffen Klassert <steffen.klassert@secunet.com>
Mon, 5 Dec 2022 09:32:44 +0000 (10:32 +0100)
Allow users to configure xfrm states with packet offload mode.
The packet mode must be requested both for policy and state, and
such requires us to do not implement fallback.

We explicitly return an error if requested packet mode can't
be configured.

Reviewed-by: Raed Salem <raeds@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
drivers/net/ethernet/intel/ixgbevf/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
drivers/net/ethernet/netronome/nfp/crypto/ipsec.c
drivers/net/netdevsim/ipsec.c
net/xfrm/xfrm_device.c

index 5855905200761c5c596905c476d34d3786da73bc..ca21794281d6a6f561db33a45839ed217fb1e997 100644 (file)
@@ -283,6 +283,10 @@ static int ch_ipsec_xfrm_add_state(struct xfrm_state *x)
                pr_debug("Cannot offload xfrm states with geniv other than seqiv\n");
                return -EINVAL;
        }
+       if (x->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
+               pr_debug("Unsupported xfrm offload\n");
+               return -EINVAL;
+       }
 
        sa_entry = kzalloc(sizeof(*sa_entry), GFP_KERNEL);
        if (!sa_entry) {
index 774de63dd93a605e7d3e82eefca8be57fd21b724..53a969e348836aedbb76b6e3300bad7301e9e0a4 100644 (file)
@@ -585,6 +585,11 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
                return -EINVAL;
        }
 
+       if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
+               netdev_err(dev, "Unsupported ipsec offload type\n");
+               return -EINVAL;
+       }
+
        if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) {
                struct rx_sa rsa;
 
index 9984ebc62d78768339e3b34a1854088126b9f3a1..c1cf540d162a89da68a516ef45defcddd2a884e4 100644 (file)
@@ -280,6 +280,11 @@ static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs)
                return -EINVAL;
        }
 
+       if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
+               netdev_err(dev, "Unsupported ipsec offload type\n");
+               return -EINVAL;
+       }
+
        if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) {
                struct rx_sa rsa;
 
index 1b03ab03fc5a3743c072a5509250ffd687b42a91..e6411533f9112def184362387d8961b0b0f6c2ca 100644 (file)
@@ -253,6 +253,10 @@ static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x)
                netdev_info(netdev, "Cannot offload xfrm states with geniv other than seqiv\n");
                return -EINVAL;
        }
+       if (x->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
+               netdev_info(netdev, "Unsupported xfrm offload type\n");
+               return -EINVAL;
+       }
        return 0;
 }
 
index 3728870d8e9c06847ddfa3658c6b8dcd22b7978b..4632268695cb9558b4f1349e60de3be57702a60c 100644 (file)
@@ -302,6 +302,11 @@ static int nfp_net_xfrm_add_state(struct xfrm_state *x)
                return -EINVAL;
        }
 
+       if (x->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
+               nn_err(nn, "Unsupported xfrm offload tyoe\n");
+               return -EINVAL;
+       }
+
        cfg->spi = ntohl(x->id.spi);
 
        /* Hash/Authentication */
index 386336a38f349d41692d8564783ec4c5e23f11af..b93baf5c8bee09a50a79692f9d0df0b566f80d61 100644 (file)
@@ -149,6 +149,11 @@ static int nsim_ipsec_add_sa(struct xfrm_state *xs)
                return -EINVAL;
        }
 
+       if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
+               netdev_err(dev, "Unsupported ipsec offload type\n");
+               return -EINVAL;
+       }
+
        /* find the first unused index */
        ret = nsim_ipsec_find_empty_idx(ipsec);
        if (ret < 0) {
index 3b0c1ca8d4bb6ad295f07e7dbca49674559aab22..3184b2c394b6a245e58c3758e2f99bc1ac619fe9 100644 (file)
@@ -229,6 +229,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
        struct xfrm_dev_offload *xso = &x->xso;
        xfrm_address_t *saddr;
        xfrm_address_t *daddr;
+       bool is_packet_offload;
 
        if (!x->type_offload) {
                NL_SET_ERR_MSG(extack, "Type doesn't support offload");
@@ -241,11 +242,13 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
                return -EINVAL;
        }
 
-       if (xuo->flags & ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND)) {
+       if (xuo->flags &
+           ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND | XFRM_OFFLOAD_PACKET)) {
                NL_SET_ERR_MSG(extack, "Unrecognized flags in offload request");
                return -EINVAL;
        }
 
+       is_packet_offload = xuo->flags & XFRM_OFFLOAD_PACKET;
        dev = dev_get_by_index(net, xuo->ifindex);
        if (!dev) {
                if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) {
@@ -260,7 +263,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
                                        x->props.family,
                                        xfrm_smark_get(0, x));
                if (IS_ERR(dst))
-                       return 0;
+                       return (is_packet_offload) ? -EINVAL : 0;
 
                dev = dst->dev;
 
@@ -271,7 +274,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
        if (!dev->xfrmdev_ops || !dev->xfrmdev_ops->xdo_dev_state_add) {
                xso->dev = NULL;
                dev_put(dev);
-               return 0;
+               return (is_packet_offload) ? -EINVAL : 0;
        }
 
        if (x->props.flags & XFRM_STATE_ESN &&
@@ -291,7 +294,10 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
        else
                xso->dir = XFRM_DEV_OFFLOAD_OUT;
 
-       xso->type = XFRM_DEV_OFFLOAD_CRYPTO;
+       if (is_packet_offload)
+               xso->type = XFRM_DEV_OFFLOAD_PACKET;
+       else
+               xso->type = XFRM_DEV_OFFLOAD_CRYPTO;
 
        err = dev->xfrmdev_ops->xdo_dev_state_add(x);
        if (err) {
@@ -301,7 +307,15 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
                netdev_put(dev, &xso->dev_tracker);
                xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
 
-               if (err != -EOPNOTSUPP) {
+               /* User explicitly requested packet offload mode and configured
+                * policy in addition to the XFRM state. So be civil to users,
+                * and return an error instead of taking fallback path.
+                *
+                * This WARN_ON() can be seen as a documentation for driver
+                * authors to do not return -EOPNOTSUPP in packet offload mode.
+                */
+               WARN_ON(err == -EOPNOTSUPP && is_packet_offload);
+               if (err != -EOPNOTSUPP || is_packet_offload) {
                        NL_SET_ERR_MSG(extack, "Device failed to offload this state");
                        return err;
                }