net/mlx5e: Support IPsec NAT-T functionality
Extend mlx5 IPsec packet offload to support UDP encapsulation of IPsec ESP packets. Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
4acea83a84
commit
d659549349
@ -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,
|
|||||||
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 {
|
|||||||
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 @@ free_reformatbf:
|
|||||||
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 =
|
|
||||||
MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV6;
|
|
||||||
|
|
||||||
reformatbf = kzalloc(MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE,
|
reformatbf = kzalloc(bfflen, GFP_KERNEL);
|
||||||
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:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user