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 5855905..ca21794 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 774de63..53a969e 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 9984ebc..c1cf540 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 1b03ab0..e641153 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 3728870..4632268 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 386336a..b93baf5 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 3b0c1ca..3184b2c 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;
                }