Commit e8a292d6 authored by Steffen Klassert's avatar Steffen Klassert

Merge branch 'mlx5 IPsec packet offload support (Part I)'

Leon Romanovsky says:

============
This series follows previously sent "Extend XFRM core to allow packet
offload configuration" series [1].

It is first part with refactoring to mlx5 allow us natively extend
mlx5 IPsec logic to support both crypto and packet offloads.
============
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parents 89ae6573 a8e05293
...@@ -1245,4 +1245,5 @@ int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate, int max_t ...@@ -1245,4 +1245,5 @@ int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate, int max_t
int mlx5e_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi); int mlx5e_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi);
int mlx5e_get_vf_stats(struct net_device *dev, int vf, struct ifla_vf_stats *vf_stats); int mlx5e_get_vf_stats(struct net_device *dev, int vf, struct ifla_vf_stats *vf_stats);
#endif #endif
int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, u32 *mkey);
#endif /* __MLX5_EN_H__ */ #endif /* __MLX5_EN_H__ */
...@@ -162,7 +162,6 @@ mlx5e_tc_meter_modify(struct mlx5_core_dev *mdev, ...@@ -162,7 +162,6 @@ mlx5e_tc_meter_modify(struct mlx5_core_dev *mdev,
MLX5_ACCESS_ASO_OPC_MOD_FLOW_METER); MLX5_ACCESS_ASO_OPC_MOD_FLOW_METER);
aso_ctrl = &aso_wqe->aso_ctrl; aso_ctrl = &aso_wqe->aso_ctrl;
memset(aso_ctrl, 0, sizeof(*aso_ctrl));
aso_ctrl->data_mask_mode = MLX5_ASO_DATA_MASK_MODE_BYTEWISE_64BYTE << 6; aso_ctrl->data_mask_mode = MLX5_ASO_DATA_MASK_MODE_BYTEWISE_64BYTE << 6;
aso_ctrl->condition_1_0_operand = MLX5_ASO_ALWAYS_TRUE | aso_ctrl->condition_1_0_operand = MLX5_ASO_ALWAYS_TRUE |
MLX5_ASO_ALWAYS_TRUE << 4; MLX5_ASO_ALWAYS_TRUE << 4;
......
...@@ -162,28 +162,21 @@ mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, ...@@ -162,28 +162,21 @@ mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
/* esn */ /* esn */
if (sa_entry->esn_state.trigger) { if (sa_entry->esn_state.trigger) {
attrs->flags |= MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED; attrs->esn_trigger = true;
attrs->esn = sa_entry->esn_state.esn; attrs->esn = sa_entry->esn_state.esn;
if (sa_entry->esn_state.overlap) attrs->esn_overlap = sa_entry->esn_state.overlap;
attrs->flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP; attrs->replay_window = x->replay_esn->replay_window;
} }
/* action */ attrs->dir = x->xso.dir;
attrs->action = (x->xso.dir == XFRM_DEV_OFFLOAD_OUT) ?
MLX5_ACCEL_ESP_ACTION_ENCRYPT :
MLX5_ACCEL_ESP_ACTION_DECRYPT;
/* flags */
attrs->flags |= (x->props.mode == XFRM_MODE_TRANSPORT) ?
MLX5_ACCEL_ESP_FLAGS_TRANSPORT :
MLX5_ACCEL_ESP_FLAGS_TUNNEL;
/* spi */ /* spi */
attrs->spi = be32_to_cpu(x->id.spi); attrs->spi = be32_to_cpu(x->id.spi);
/* source , destination ips */ /* source , destination ips */
memcpy(&attrs->saddr, x->props.saddr.a6, sizeof(attrs->saddr)); memcpy(&attrs->saddr, x->props.saddr.a6, sizeof(attrs->saddr));
memcpy(&attrs->daddr, x->id.daddr.a6, sizeof(attrs->daddr)); memcpy(&attrs->daddr, x->id.daddr.a6, sizeof(attrs->daddr));
attrs->is_ipv6 = (x->props.family != AF_INET); attrs->family = x->props.family;
attrs->type = x->xso.type;
} }
static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x) static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x)
...@@ -257,6 +250,17 @@ static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x) ...@@ -257,6 +250,17 @@ static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x)
netdev_info(netdev, "Unsupported xfrm offload type\n"); netdev_info(netdev, "Unsupported xfrm offload type\n");
return -EINVAL; return -EINVAL;
} }
if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) {
if (x->replay_esn && x->replay_esn->replay_window != 32 &&
x->replay_esn->replay_window != 64 &&
x->replay_esn->replay_window != 128 &&
x->replay_esn->replay_window != 256) {
netdev_info(netdev,
"Unsupported replay window size %u\n",
x->replay_esn->replay_window);
return -EINVAL;
}
}
return 0; return 0;
} }
...@@ -303,7 +307,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x) ...@@ -303,7 +307,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x)
if (err) if (err)
goto err_xfrm; goto err_xfrm;
err = mlx5e_accel_ipsec_fs_add_rule(priv, sa_entry); err = mlx5e_accel_ipsec_fs_add_rule(sa_entry);
if (err) if (err)
goto err_hw_ctx; goto err_hw_ctx;
...@@ -321,7 +325,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x) ...@@ -321,7 +325,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x)
goto out; goto out;
err_add_rule: err_add_rule:
mlx5e_accel_ipsec_fs_del_rule(priv, sa_entry); mlx5e_accel_ipsec_fs_del_rule(sa_entry);
err_hw_ctx: err_hw_ctx:
mlx5_ipsec_free_sa_ctx(sa_entry); mlx5_ipsec_free_sa_ctx(sa_entry);
err_xfrm: err_xfrm:
...@@ -341,10 +345,9 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x) ...@@ -341,10 +345,9 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
static void mlx5e_xfrm_free_state(struct xfrm_state *x) static void mlx5e_xfrm_free_state(struct xfrm_state *x)
{ {
struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x); struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
struct mlx5e_priv *priv = netdev_priv(x->xso.dev);
cancel_work_sync(&sa_entry->modify_work.work); cancel_work_sync(&sa_entry->modify_work.work);
mlx5e_accel_ipsec_fs_del_rule(priv, sa_entry); mlx5e_accel_ipsec_fs_del_rule(sa_entry);
mlx5_ipsec_free_sa_ctx(sa_entry); mlx5_ipsec_free_sa_ctx(sa_entry);
kfree(sa_entry); kfree(sa_entry);
} }
...@@ -371,15 +374,26 @@ void mlx5e_ipsec_init(struct mlx5e_priv *priv) ...@@ -371,15 +374,26 @@ void mlx5e_ipsec_init(struct mlx5e_priv *priv)
if (!ipsec->wq) if (!ipsec->wq)
goto err_wq; goto err_wq;
if (mlx5_ipsec_device_caps(priv->mdev) &
MLX5_IPSEC_CAP_PACKET_OFFLOAD) {
ret = mlx5e_ipsec_aso_init(ipsec);
if (ret)
goto err_aso;
}
ret = mlx5e_accel_ipsec_fs_init(ipsec); ret = mlx5e_accel_ipsec_fs_init(ipsec);
if (ret) if (ret)
goto err_fs_init; goto err_fs_init;
ipsec->fs = priv->fs;
priv->ipsec = ipsec; priv->ipsec = ipsec;
netdev_dbg(priv->netdev, "IPSec attached to netdevice\n"); netdev_dbg(priv->netdev, "IPSec attached to netdevice\n");
return; return;
err_fs_init: err_fs_init:
if (mlx5_ipsec_device_caps(priv->mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD)
mlx5e_ipsec_aso_cleanup(ipsec);
err_aso:
destroy_workqueue(ipsec->wq); destroy_workqueue(ipsec->wq);
err_wq: err_wq:
kfree(ipsec); kfree(ipsec);
...@@ -395,6 +409,8 @@ void mlx5e_ipsec_cleanup(struct mlx5e_priv *priv) ...@@ -395,6 +409,8 @@ void mlx5e_ipsec_cleanup(struct mlx5e_priv *priv)
return; return;
mlx5e_accel_ipsec_fs_cleanup(ipsec); mlx5e_accel_ipsec_fs_cleanup(ipsec);
if (mlx5_ipsec_device_caps(priv->mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD)
mlx5e_ipsec_aso_cleanup(ipsec);
destroy_workqueue(ipsec->wq); destroy_workqueue(ipsec->wq);
kfree(ipsec); kfree(ipsec);
priv->ipsec = NULL; priv->ipsec = NULL;
......
...@@ -39,22 +39,11 @@ ...@@ -39,22 +39,11 @@
#include <linux/mlx5/device.h> #include <linux/mlx5/device.h>
#include <net/xfrm.h> #include <net/xfrm.h>
#include <linux/idr.h> #include <linux/idr.h>
#include "lib/aso.h"
#define MLX5E_IPSEC_SADB_RX_BITS 10 #define MLX5E_IPSEC_SADB_RX_BITS 10
#define MLX5E_IPSEC_ESN_SCOPE_MID 0x80000000L #define MLX5E_IPSEC_ESN_SCOPE_MID 0x80000000L
enum mlx5_accel_esp_flags {
MLX5_ACCEL_ESP_FLAGS_TUNNEL = 0, /* Default */
MLX5_ACCEL_ESP_FLAGS_TRANSPORT = 1UL << 0,
MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED = 1UL << 1,
MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP = 1UL << 2,
};
enum mlx5_accel_esp_action {
MLX5_ACCEL_ESP_ACTION_DECRYPT,
MLX5_ACCEL_ESP_ACTION_ENCRYPT,
};
struct aes_gcm_keymat { struct aes_gcm_keymat {
u64 seq_iv; u64 seq_iv;
...@@ -66,7 +55,6 @@ struct aes_gcm_keymat { ...@@ -66,7 +55,6 @@ struct aes_gcm_keymat {
}; };
struct mlx5_accel_esp_xfrm_attrs { struct mlx5_accel_esp_xfrm_attrs {
enum mlx5_accel_esp_action action;
u32 esn; u32 esn;
u32 spi; u32 spi;
u32 flags; u32 flags;
...@@ -82,12 +70,18 @@ struct mlx5_accel_esp_xfrm_attrs { ...@@ -82,12 +70,18 @@ struct mlx5_accel_esp_xfrm_attrs {
__be32 a6[4]; __be32 a6[4];
} daddr; } daddr;
u8 is_ipv6; u8 dir : 2;
u8 esn_overlap : 1;
u8 esn_trigger : 1;
u8 type : 2;
u8 family;
u32 replay_window;
}; };
enum mlx5_ipsec_cap { enum mlx5_ipsec_cap {
MLX5_IPSEC_CAP_CRYPTO = 1 << 0, MLX5_IPSEC_CAP_CRYPTO = 1 << 0,
MLX5_IPSEC_CAP_ESN = 1 << 1, MLX5_IPSEC_CAP_ESN = 1 << 1,
MLX5_IPSEC_CAP_PACKET_OFFLOAD = 1 << 2,
}; };
struct mlx5e_priv; struct mlx5e_priv;
...@@ -102,17 +96,26 @@ struct mlx5e_ipsec_sw_stats { ...@@ -102,17 +96,26 @@ struct mlx5e_ipsec_sw_stats {
atomic64_t ipsec_tx_drop_trailer; atomic64_t ipsec_tx_drop_trailer;
}; };
struct mlx5e_accel_fs_esp; struct mlx5e_ipsec_rx;
struct mlx5e_ipsec_tx; struct mlx5e_ipsec_tx;
struct mlx5e_ipsec_aso {
u8 ctx[MLX5_ST_SZ_BYTES(ipsec_aso)];
dma_addr_t dma_addr;
struct mlx5_aso *aso;
};
struct mlx5e_ipsec { struct mlx5e_ipsec {
struct mlx5_core_dev *mdev; struct mlx5_core_dev *mdev;
DECLARE_HASHTABLE(sadb_rx, MLX5E_IPSEC_SADB_RX_BITS); DECLARE_HASHTABLE(sadb_rx, MLX5E_IPSEC_SADB_RX_BITS);
spinlock_t sadb_rx_lock; /* Protects sadb_rx */ spinlock_t sadb_rx_lock; /* Protects sadb_rx */
struct mlx5e_ipsec_sw_stats sw_stats; struct mlx5e_ipsec_sw_stats sw_stats;
struct workqueue_struct *wq; struct workqueue_struct *wq;
struct mlx5e_accel_fs_esp *rx_fs; struct mlx5e_flow_steering *fs;
struct mlx5e_ipsec_tx *tx_fs; struct mlx5e_ipsec_rx *rx_ipv4;
struct mlx5e_ipsec_rx *rx_ipv6;
struct mlx5e_ipsec_tx *tx;
struct mlx5e_ipsec_aso *aso;
}; };
struct mlx5e_ipsec_esn_state { struct mlx5e_ipsec_esn_state {
...@@ -123,7 +126,7 @@ struct mlx5e_ipsec_esn_state { ...@@ -123,7 +126,7 @@ struct mlx5e_ipsec_esn_state {
struct mlx5e_ipsec_rule { struct mlx5e_ipsec_rule {
struct mlx5_flow_handle *rule; struct mlx5_flow_handle *rule;
struct mlx5_modify_hdr *set_modify_hdr; struct mlx5_modify_hdr *modify_hdr;
}; };
struct mlx5e_ipsec_modify_state_work { struct mlx5e_ipsec_modify_state_work {
...@@ -155,10 +158,8 @@ struct xfrm_state *mlx5e_ipsec_sadb_rx_lookup(struct mlx5e_ipsec *dev, ...@@ -155,10 +158,8 @@ struct xfrm_state *mlx5e_ipsec_sadb_rx_lookup(struct mlx5e_ipsec *dev,
void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec); void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec);
int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec); int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec);
int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_priv *priv, int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry);
struct mlx5e_ipsec_sa_entry *sa_entry); void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry);
void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_priv *priv,
struct mlx5e_ipsec_sa_entry *sa_entry);
int mlx5_ipsec_create_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry); int mlx5_ipsec_create_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry);
void mlx5_ipsec_free_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry); void mlx5_ipsec_free_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry);
...@@ -168,6 +169,9 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev); ...@@ -168,6 +169,9 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev);
void mlx5_accel_esp_modify_xfrm(struct mlx5e_ipsec_sa_entry *sa_entry, void mlx5_accel_esp_modify_xfrm(struct mlx5e_ipsec_sa_entry *sa_entry,
const struct mlx5_accel_esp_xfrm_attrs *attrs); const struct mlx5_accel_esp_xfrm_attrs *attrs);
int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec);
void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec);
static inline struct mlx5_core_dev * static inline struct mlx5_core_dev *
mlx5e_ipsec_sa2dev(struct mlx5e_ipsec_sa_entry *sa_entry) mlx5e_ipsec_sa2dev(struct mlx5e_ipsec_sa_entry *sa_entry)
{ {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. */ /* Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. */
#include "mlx5_core.h" #include "mlx5_core.h"
#include "en.h"
#include "ipsec.h" #include "ipsec.h"
#include "lib/mlx5.h" #include "lib/mlx5.h"
...@@ -31,6 +32,12 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev) ...@@ -31,6 +32,12 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev)
MLX5_CAP_ETH(mdev, insert_trailer) && MLX5_CAP_ETH(mdev, swp)) MLX5_CAP_ETH(mdev, insert_trailer) && MLX5_CAP_ETH(mdev, swp))
caps |= MLX5_IPSEC_CAP_CRYPTO; caps |= MLX5_IPSEC_CAP_CRYPTO;
if (MLX5_CAP_IPSEC(mdev, ipsec_full_offload) &&
MLX5_CAP_FLOWTABLE_NIC_TX(mdev, reformat_add_esp_trasport) &&
MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_del_esp_trasport) &&
MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap))
caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD;
if (!caps) if (!caps)
return 0; return 0;
...@@ -46,6 +53,38 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev) ...@@ -46,6 +53,38 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev)
} }
EXPORT_SYMBOL_GPL(mlx5_ipsec_device_caps); EXPORT_SYMBOL_GPL(mlx5_ipsec_device_caps);
static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn,
struct mlx5_accel_esp_xfrm_attrs *attrs)
{
void *aso_ctx;
aso_ctx = MLX5_ADDR_OF(ipsec_obj, obj, ipsec_aso);
if (attrs->esn_trigger) {
MLX5_SET(ipsec_aso, aso_ctx, esn_event_arm, 1);
if (attrs->dir == XFRM_DEV_OFFLOAD_IN) {
MLX5_SET(ipsec_aso, aso_ctx, window_sz,
attrs->replay_window / 64);
MLX5_SET(ipsec_aso, aso_ctx, mode,
MLX5_IPSEC_ASO_REPLAY_PROTECTION);
}
}
/* ASO context */
MLX5_SET(ipsec_obj, obj, ipsec_aso_access_pd, pdn);
MLX5_SET(ipsec_obj, obj, full_offload, 1);
MLX5_SET(ipsec_aso, aso_ctx, valid, 1);
/* MLX5_IPSEC_ASO_REG_C_4_5 is type C register that is used
* in flow steering to perform matching against. Please be
* aware that this register was chosen arbitrary and can't
* be used in other places as long as IPsec packet offload
* active.
*/
MLX5_SET(ipsec_obj, obj, aso_return_reg, MLX5_IPSEC_ASO_REG_C_4_5);
if (attrs->dir == XFRM_DEV_OFFLOAD_OUT)
MLX5_SET(ipsec_aso, aso_ctx, mode, MLX5_IPSEC_ASO_INC_SN);
}
static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry) static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
{ {
struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs;
...@@ -54,6 +93,7 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry) ...@@ -54,6 +93,7 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
u32 in[MLX5_ST_SZ_DW(create_ipsec_obj_in)] = {}; u32 in[MLX5_ST_SZ_DW(create_ipsec_obj_in)] = {};
void *obj, *salt_p, *salt_iv_p; void *obj, *salt_p, *salt_iv_p;
struct mlx5e_hw_objs *res;
int err; int err;
obj = MLX5_ADDR_OF(create_ipsec_obj_in, in, ipsec_object); obj = MLX5_ADDR_OF(create_ipsec_obj_in, in, ipsec_object);
...@@ -66,11 +106,10 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry) ...@@ -66,11 +106,10 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
salt_iv_p = MLX5_ADDR_OF(ipsec_obj, obj, implicit_iv); salt_iv_p = MLX5_ADDR_OF(ipsec_obj, obj, implicit_iv);
memcpy(salt_iv_p, &aes_gcm->seq_iv, sizeof(aes_gcm->seq_iv)); memcpy(salt_iv_p, &aes_gcm->seq_iv, sizeof(aes_gcm->seq_iv));
/* esn */ /* esn */
if (attrs->flags & MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED) { if (attrs->esn_trigger) {
MLX5_SET(ipsec_obj, obj, esn_en, 1); MLX5_SET(ipsec_obj, obj, esn_en, 1);
MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn); MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn);
if (attrs->flags & MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP) MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->esn_overlap);
MLX5_SET(ipsec_obj, obj, esn_overlap, 1);
} }
MLX5_SET(ipsec_obj, obj, dekn, sa_entry->enc_key_id); MLX5_SET(ipsec_obj, obj, dekn, sa_entry->enc_key_id);
...@@ -81,6 +120,10 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry) ...@@ -81,6 +120,10 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
MLX5_GENERAL_OBJECT_TYPES_IPSEC); MLX5_GENERAL_OBJECT_TYPES_IPSEC);
res = &mdev->mlx5e_res.hw_objs;
if (attrs->type == XFRM_DEV_OFFLOAD_PACKET)
mlx5e_ipsec_packet_setup(obj, res->pdn, attrs);
err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
if (!err) if (!err)
sa_entry->ipsec_obj_id = sa_entry->ipsec_obj_id =
...@@ -152,7 +195,7 @@ static int mlx5_modify_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ...@@ -152,7 +195,7 @@ static int mlx5_modify_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
void *obj; void *obj;
int err; int err;
if (!(attrs->flags & MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED)) if (!attrs->esn_trigger)
return 0; return 0;
general_obj_types = MLX5_CAP_GEN_64(mdev, general_obj_types); general_obj_types = MLX5_CAP_GEN_64(mdev, general_obj_types);
...@@ -183,8 +226,7 @@ static int mlx5_modify_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry, ...@@ -183,8 +226,7 @@ static int mlx5_modify_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
MLX5_MODIFY_IPSEC_BITMASK_ESN_OVERLAP | MLX5_MODIFY_IPSEC_BITMASK_ESN_OVERLAP |
MLX5_MODIFY_IPSEC_BITMASK_ESN_MSB); MLX5_MODIFY_IPSEC_BITMASK_ESN_MSB);
MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn); MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn);
if (attrs->flags & MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP) MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->esn_overlap);
MLX5_SET(ipsec_obj, obj, esn_overlap, 1);
/* general object fields set */ /* general object fields set */
MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT); MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
...@@ -203,3 +245,56 @@ void mlx5_accel_esp_modify_xfrm(struct mlx5e_ipsec_sa_entry *sa_entry, ...@@ -203,3 +245,56 @@ void mlx5_accel_esp_modify_xfrm(struct mlx5e_ipsec_sa_entry *sa_entry,
memcpy(&sa_entry->attrs, attrs, sizeof(sa_entry->attrs)); memcpy(&sa_entry->attrs, attrs, sizeof(sa_entry->attrs));
} }
int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec)
{
struct mlx5_core_dev *mdev = ipsec->mdev;
struct mlx5e_ipsec_aso *aso;
struct mlx5e_hw_objs *res;
struct device *pdev;
int err;
aso = kzalloc(sizeof(*ipsec->aso), GFP_KERNEL);
if (!aso)
return -ENOMEM;
res = &mdev->mlx5e_res.hw_objs;
pdev = mlx5_core_dma_dev(mdev);
aso->dma_addr = dma_map_single(pdev, aso->ctx, sizeof(aso->ctx),
DMA_BIDIRECTIONAL);
err = dma_mapping_error(pdev, aso->dma_addr);
if (err)
goto err_dma;
aso->aso = mlx5_aso_create(mdev, res->pdn);
if (IS_ERR(aso->aso)) {
err = PTR_ERR(aso->aso);
goto err_aso_create;
}
ipsec->aso = aso;
return 0;
err_aso_create:
dma_unmap_single(pdev, aso->dma_addr, sizeof(aso->ctx),
DMA_BIDIRECTIONAL);
err_dma:
kfree(aso);
return err;
}
void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec)
{
struct mlx5_core_dev *mdev = ipsec->mdev;
struct mlx5e_ipsec_aso *aso;
struct device *pdev;
aso = ipsec->aso;
pdev = mlx5_core_dma_dev(mdev);
mlx5_aso_destroy(aso->aso);
dma_unmap_single(pdev, aso->dma_addr, sizeof(aso->ctx),
DMA_BIDIRECTIONAL);
kfree(aso);
}
...@@ -353,12 +353,15 @@ void mlx5_aso_build_wqe(struct mlx5_aso *aso, u8 ds_cnt, ...@@ -353,12 +353,15 @@ void mlx5_aso_build_wqe(struct mlx5_aso *aso, u8 ds_cnt,
cseg->general_id = cpu_to_be32(obj_id); cseg->general_id = cpu_to_be32(obj_id);
} }
void *mlx5_aso_get_wqe(struct mlx5_aso *aso) struct mlx5_aso_wqe *mlx5_aso_get_wqe(struct mlx5_aso *aso)
{ {
struct mlx5_aso_wqe *wqe;
u16 pi; u16 pi;
pi = mlx5_wq_cyc_ctr2ix(&aso->wq, aso->pc); pi = mlx5_wq_cyc_ctr2ix(&aso->wq, aso->pc);
return mlx5_wq_cyc_get_wqe(&aso->wq, pi); wqe = mlx5_wq_cyc_get_wqe(&aso->wq, pi);
memset(wqe, 0, sizeof(*wqe));
return wqe;
} }
void mlx5_aso_post_wqe(struct mlx5_aso *aso, bool with_data, void mlx5_aso_post_wqe(struct mlx5_aso *aso, bool with_data,
......
...@@ -71,13 +71,14 @@ enum { ...@@ -71,13 +71,14 @@ enum {
}; };
enum { enum {
MLX5_ACCESS_ASO_OPC_MOD_IPSEC = 0x0,
MLX5_ACCESS_ASO_OPC_MOD_FLOW_METER = 0x2, MLX5_ACCESS_ASO_OPC_MOD_FLOW_METER = 0x2,
MLX5_ACCESS_ASO_OPC_MOD_MACSEC = 0x5, MLX5_ACCESS_ASO_OPC_MOD_MACSEC = 0x5,
}; };
struct mlx5_aso; struct mlx5_aso;
void *mlx5_aso_get_wqe(struct mlx5_aso *aso); struct mlx5_aso_wqe *mlx5_aso_get_wqe(struct mlx5_aso *aso);
void mlx5_aso_build_wqe(struct mlx5_aso *aso, u8 ds_cnt, void mlx5_aso_build_wqe(struct mlx5_aso *aso, u8 ds_cnt,
struct mlx5_aso_wqe *aso_wqe, struct mlx5_aso_wqe *aso_wqe,
u32 obj_id, u32 opc_mode); u32 obj_id, u32 opc_mode);
......
...@@ -445,7 +445,10 @@ struct mlx5_ifc_flow_table_prop_layout_bits { ...@@ -445,7 +445,10 @@ struct mlx5_ifc_flow_table_prop_layout_bits {
u8 max_modify_header_actions[0x8]; u8 max_modify_header_actions[0x8];
u8 max_ft_level[0x8]; u8 max_ft_level[0x8];
u8 reserved_at_40[0x6]; u8 reformat_add_esp_trasport[0x1];
u8 reserved_at_41[0x2];
u8 reformat_del_esp_trasport[0x1];
u8 reserved_at_44[0x2];
u8 execute_aso[0x1]; u8 execute_aso[0x1];
u8 reserved_at_47[0x19]; u8 reserved_at_47[0x19];
...@@ -638,8 +641,10 @@ struct mlx5_ifc_fte_match_set_misc2_bits { ...@@ -638,8 +641,10 @@ struct mlx5_ifc_fte_match_set_misc2_bits {
u8 reserved_at_1a0[0x8]; u8 reserved_at_1a0[0x8];
u8 macsec_syndrome[0x8]; u8 macsec_syndrome[0x8];
u8 ipsec_syndrome[0x8];
u8 reserved_at_1b8[0x8];
u8 reserved_at_1b0[0x50]; u8 reserved_at_1c0[0x40];
}; };
struct mlx5_ifc_fte_match_set_misc3_bits { struct mlx5_ifc_fte_match_set_misc3_bits {
...@@ -6384,6 +6389,9 @@ enum mlx5_reformat_ctx_type { ...@@ -6384,6 +6389,9 @@ enum mlx5_reformat_ctx_type {
MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL = 0x2, MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL = 0x2,
MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2 = 0x3, MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2 = 0x3,
MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL = 0x4, MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL = 0x4,
MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV4 = 0x5,
MLX5_REFORMAT_TYPE_DEL_ESP_TRANSPORT = 0x8,
MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_OVER_IPV6 = 0xb,
MLX5_REFORMAT_TYPE_INSERT_HDR = 0xf, MLX5_REFORMAT_TYPE_INSERT_HDR = 0xf,
MLX5_REFORMAT_TYPE_REMOVE_HDR = 0x10, MLX5_REFORMAT_TYPE_REMOVE_HDR = 0x10,
MLX5_REFORMAT_TYPE_ADD_MACSEC = 0x11, MLX5_REFORMAT_TYPE_ADD_MACSEC = 0x11,
...@@ -11563,6 +11571,41 @@ enum { ...@@ -11563,6 +11571,41 @@ enum {
MLX5_IPSEC_OBJECT_ICV_LEN_16B, MLX5_IPSEC_OBJECT_ICV_LEN_16B,
}; };
enum {
MLX5_IPSEC_ASO_REG_C_0_1 = 0x0,
MLX5_IPSEC_ASO_REG_C_2_3 = 0x1,
MLX5_IPSEC_ASO_REG_C_4_5 = 0x2,
MLX5_IPSEC_ASO_REG_C_6_7 = 0x3,
};
enum {
MLX5_IPSEC_ASO_MODE = 0x0,
MLX5_IPSEC_ASO_REPLAY_PROTECTION = 0x1,
MLX5_IPSEC_ASO_INC_SN = 0x2,
};
struct mlx5_ifc_ipsec_aso_bits {
u8 valid[0x1];
u8 reserved_at_201[0x1];
u8 mode[0x2];
u8 window_sz[0x2];
u8 soft_lft_arm[0x1];
u8 hard_lft_arm[0x1];
u8 remove_flow_enable[0x1];
u8 esn_event_arm[0x1];
u8 reserved_at_20a[0x16];
u8 remove_flow_pkt_cnt[0x20];
u8 remove_flow_soft_lft[0x20];
u8 reserved_at_260[0x80];
u8 mode_parameter[0x20];
u8 replay_protection_window[0x100];
};
struct mlx5_ifc_ipsec_obj_bits { struct mlx5_ifc_ipsec_obj_bits {
u8 modify_field_select[0x40]; u8 modify_field_select[0x40];
u8 full_offload[0x1]; u8 full_offload[0x1];
...@@ -11584,7 +11627,11 @@ struct mlx5_ifc_ipsec_obj_bits { ...@@ -11584,7 +11627,11 @@ struct mlx5_ifc_ipsec_obj_bits {
u8 implicit_iv[0x40]; u8 implicit_iv[0x40];
u8 reserved_at_100[0x700]; u8 reserved_at_100[0x8];
u8 ipsec_aso_access_pd[0x18];
u8 reserved_at_120[0xe0];
struct mlx5_ifc_ipsec_aso_bits ipsec_aso;
}; };
struct mlx5_ifc_create_ipsec_obj_in_bits { struct mlx5_ifc_create_ipsec_obj_in_bits {
......
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