xfrm: allow state packet offload mode
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>
This commit is contained in:
parent
d14f28b8c1
commit
62f6eca5de
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue