Commit d6595493 authored by Leon Romanovsky's avatar Leon Romanovsky Committed by Paolo Abeni

net/mlx5e: Support IPsec NAT-T functionality

Extend mlx5 IPsec packet offload to support UDP encapsulation
of IPsec ESP packets.
Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 4acea83a
...@@ -354,6 +354,12 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, ...@@ -354,6 +354,12 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
mlx5e_ipsec_init_limits(sa_entry, attrs); mlx5e_ipsec_init_limits(sa_entry, attrs);
mlx5e_ipsec_init_macs(sa_entry, attrs); mlx5e_ipsec_init_macs(sa_entry, attrs);
if (x->encap) {
attrs->encap = true;
attrs->sport = x->encap->encap_sport;
attrs->dport = x->encap->encap_dport;
}
} }
static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev, static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev,
...@@ -387,8 +393,25 @@ static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev, ...@@ -387,8 +393,25 @@ static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev,
return -EINVAL; return -EINVAL;
} }
if (x->encap) { if (x->encap) {
NL_SET_ERR_MSG_MOD(extack, "Encapsulated xfrm state may not be offloaded"); if (!(mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ESPINUDP)) {
return -EINVAL; NL_SET_ERR_MSG_MOD(extack, "Encapsulation is not supported");
return -EINVAL;
}
if (x->encap->encap_type != UDP_ENCAP_ESPINUDP) {
NL_SET_ERR_MSG_MOD(extack, "Encapsulation other than UDP is not supported");
return -EINVAL;
}
if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET) {
NL_SET_ERR_MSG_MOD(extack, "Encapsulation is supported in packet offload mode only");
return -EINVAL;
}
if (x->props.mode != XFRM_MODE_TRANSPORT) {
NL_SET_ERR_MSG_MOD(extack, "Encapsulation is supported in transport mode only");
return -EINVAL;
}
} }
if (!x->aead) { if (!x->aead) {
NL_SET_ERR_MSG_MOD(extack, "Cannot offload xfrm states without aead"); NL_SET_ERR_MSG_MOD(extack, "Cannot offload xfrm states without aead");
......
...@@ -94,13 +94,20 @@ struct mlx5_accel_esp_xfrm_attrs { ...@@ -94,13 +94,20 @@ struct mlx5_accel_esp_xfrm_attrs {
u8 dir : 2; u8 dir : 2;
u8 type : 2; u8 type : 2;
u8 drop : 1; u8 drop : 1;
u8 encap : 1;
u8 family; u8 family;
struct mlx5_replay_esn replay_esn; struct mlx5_replay_esn replay_esn;
u32 authsize; u32 authsize;
u32 reqid; u32 reqid;
struct mlx5_ipsec_lft lft; struct mlx5_ipsec_lft lft;
u8 smac[ETH_ALEN]; union {
u8 dmac[ETH_ALEN]; u8 smac[ETH_ALEN];
__be16 sport;
};
union {
u8 dmac[ETH_ALEN];
__be16 dport;
};
}; };
enum mlx5_ipsec_cap { enum mlx5_ipsec_cap {
......
...@@ -951,37 +951,70 @@ setup_pkt_tunnel_reformat(struct mlx5_core_dev *mdev, ...@@ -951,37 +951,70 @@ setup_pkt_tunnel_reformat(struct mlx5_core_dev *mdev,
return -EINVAL; return -EINVAL;
} }
static int get_reformat_type(struct mlx5_accel_esp_xfrm_attrs *attrs)
{
switch (attrs->dir) {
case XFRM_DEV_OFFLOAD_IN:
if (attrs->encap)
return MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT_OVER_UDP;
return MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT;
case XFRM_DEV_OFFLOAD_OUT:
if (attrs->family == AF_INET) {
if (attrs->encap)
return MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_UDPV4;
return MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV4;
}
if (attrs->encap)
return MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_UDPV6;
return MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV6;
default:
WARN_ON(true);
}
return -EINVAL;
}
static int static int
setup_pkt_transport_reformat(struct mlx5_accel_esp_xfrm_attrs *attrs, setup_pkt_transport_reformat(struct mlx5_accel_esp_xfrm_attrs *attrs,
struct mlx5_pkt_reformat_params *reformat_params) struct mlx5_pkt_reformat_params *reformat_params)
{ {
u8 *reformatbf; struct udphdr *udphdr;
char *reformatbf;
size_t bfflen;
__be32 spi; __be32 spi;
void *hdr;
reformat_params->type = get_reformat_type(attrs);
if (reformat_params->type < 0)
return reformat_params->type;
switch (attrs->dir) { switch (attrs->dir) {
case XFRM_DEV_OFFLOAD_IN: case XFRM_DEV_OFFLOAD_IN:
reformat_params->type = MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT;
break; break;
case XFRM_DEV_OFFLOAD_OUT: case XFRM_DEV_OFFLOAD_OUT:
if (attrs->family == AF_INET) bfflen = MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE;
reformat_params->type = if (attrs->encap)
MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV4; bfflen += sizeof(*udphdr);
else
reformat_params->type = reformatbf = kzalloc(bfflen, GFP_KERNEL);
MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV6;
reformatbf = kzalloc(MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE,
GFP_KERNEL);
if (!reformatbf) if (!reformatbf)
return -ENOMEM; return -ENOMEM;
hdr = reformatbf;
if (attrs->encap) {
udphdr = (struct udphdr *)reformatbf;
udphdr->source = attrs->sport;
udphdr->dest = attrs->dport;
hdr += sizeof(*udphdr);
}
/* convert to network format */ /* convert to network format */
spi = htonl(attrs->spi); spi = htonl(attrs->spi);
memcpy(reformatbf, &spi, sizeof(spi)); memcpy(hdr, &spi, sizeof(spi));
reformat_params->param_0 = attrs->authsize; reformat_params->param_0 = attrs->authsize;
reformat_params->size = reformat_params->size = bfflen;
MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE;
reformat_params->data = reformatbf; reformat_params->data = reformatbf;
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment