mlx5-tls-2020-06-26
1) Improve hardware layouts and structure for kTLS support 2) Generalize ICOSQ (Internal Channel Operations Send Queue) Due to the asynchronous nature of adding new kTLS flows and handling HW asynchronous kTLS resync requests, the XSK ICOSQ was extended to support generic async operations, such as kTLS add flow and resync, in addition to the existing XSK usages. 3) kTLS hardware flow steering and classification: The driver already has the means to classify TCP ipv4/6 flows to send them to the corresponding RSS HW engine, as reflected in patches 3 through 5, the series will add a steering layer that will hook to the driver's TCP classifiers and will match on well known kTLS connection, in case of a match traffic will be redirected to the kTLS decryption engine, otherwise traffic will continue flowing normally to the TCP RSS engine. 3) kTLS add flow RX HW offload support New offload contexts post their static/progress params WQEs (Work Queue Element) to communicate the newly added kTLS contexts over the per-channel async ICOSQ. The Channel/RQ is selected according to the socket's rxq index. A new TLS-RX workqueue is used to allow asynchronous addition of steering rules, out of the NAPI context. It will be also used in a downstream patch in the resync procedure. Feature is OFF by default. Can be turned on by: $ ethtool -K <if> tls-hw-rx-offload on 4) Added mlx5 kTLS sw stats and new counters are documented in Documentation/networking/tls-offload.rst rx_tls_ctx - number of TLS RX HW offload contexts added to device for decryption. rx_tls_ooo - number of RX packets which were part of a TLS stream but did not arrive in the expected order and triggered the resync procedure. rx_tls_del - number of TLS RX HW offload contexts deleted from device (connection has finished). rx_tls_err - number of RX packets which were part of a TLS stream but were not decrypted due to unexpected error in the state machine. 5) Asynchronous RX resync a. The NIC driver indicates that it would like to resync on some TLS record within the received packet (P), but the driver does not know (yet) which of the TLS records within the packet. At this stage, the NIC driver will query the device to find the exact TCP sequence for resync (tcpsn), however, the driver does not wait for the device to provide the response. b. Eventually, the device responds, and the driver provides the tcpsn within the resync packet to KTLS. Now, KTLS can check the tcpsn against any processed TLS records within packet P, and also against any record that is processed in the future within packet P. The asynchronous resync path simplifies the device driver, as it can save bits on the packet completion (32-bit TCP sequence), and pass this information on an asynchronous command instead. Performance: CPU: Intel(R) Xeon(R) CPU E5-2687W v4 @ 3.00GHz, 24 cores, HT off NIC: ConnectX-6 Dx 100GbE dual port Goodput (app-layer throughput) comparison: +---------------+-------+-------+---------+ | # connections | 1 | 4 | 8 | +---------------+-------+-------+---------+ | SW (Gbps) | 7.26 | 24.70 | 50.30 | +---------------+-------+-------+---------+ | HW (Gbps) | 18.50 | 64.30 | 92.90 | +---------------+-------+-------+---------+ | Speedup | 2.55x | 2.56x | 1.85x * | +---------------+-------+-------+---------+ * After linerate is reached, diff is observed in CPU util -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEGhZs6bAKwk/OTgTpSD+KveBX+j4FAl73s2kACgkQSD+KveBX +j4wqAf/ZhcEn7i4N2F9wMMIL6wd4DgwKWWhbGpiREIxDwcRbqH7PGom8nBZMNd9 +3g3zfURvByWehLtYcjmMgR4B7+xDgEs0dSx6pQM9764HqLDV2jW8ENr9Vr/u8s1 hJ/eV8uzIfvx27MzbENZi0oJTw7N9nCgdcv1OyZkIba+Iado9pOeakPgBmTbINgo 46LJI9nIEROE15gfjyxrVeYAs3Nxt+bogQCWYfMqUfRmKcMJ0d4oTHaUdtmm+xQB jC685/e4gE7jRgZ3qH/xvCZYp7+TVKaXsB0EtaJdPFEkvvvQpgPTfquIQ+6l7vvE Yf1YUhnDOoxGUQy1CdSZ2reNxLIm8A== =7+rG -----END PGP SIGNATURE----- Merge tag 'mlx5-tls-2020-06-26' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux Saeed Mahameed says: ==================== mlx5-tls-2020-06-26 1) Improve hardware layouts and structure for kTLS support 2) Generalize ICOSQ (Internal Channel Operations Send Queue) Due to the asynchronous nature of adding new kTLS flows and handling HW asynchronous kTLS resync requests, the XSK ICOSQ was extended to support generic async operations, such as kTLS add flow and resync, in addition to the existing XSK usages. 3) kTLS hardware flow steering and classification: The driver already has the means to classify TCP ipv4/6 flows to send them to the corresponding RSS HW engine, as reflected in patches 3 through 5, the series will add a steering layer that will hook to the driver's TCP classifiers and will match on well known kTLS connection, in case of a match traffic will be redirected to the kTLS decryption engine, otherwise traffic will continue flowing normally to the TCP RSS engine. 3) kTLS add flow RX HW offload support New offload contexts post their static/progress params WQEs (Work Queue Element) to communicate the newly added kTLS contexts over the per-channel async ICOSQ. The Channel/RQ is selected according to the socket's rxq index. A new TLS-RX workqueue is used to allow asynchronous addition of steering rules, out of the NAPI context. It will be also used in a downstream patch in the resync procedure. Feature is OFF by default. Can be turned on by: $ ethtool -K <if> tls-hw-rx-offload on 4) Added mlx5 kTLS sw stats and new counters are documented in Documentation/networking/tls-offload.rst rx_tls_ctx - number of TLS RX HW offload contexts added to device for decryption. rx_tls_ooo - number of RX packets which were part of a TLS stream but did not arrive in the expected order and triggered the resync procedure. rx_tls_del - number of TLS RX HW offload contexts deleted from device (connection has finished). rx_tls_err - number of RX packets which were part of a TLS stream but were not decrypted due to unexpected error in the state machine. 5) Asynchronous RX resync a. The NIC driver indicates that it would like to resync on some TLS record within the received packet (P), but the driver does not know (yet) which of the TLS records within the packet. At this stage, the NIC driver will query the device to find the exact TCP sequence for resync (tcpsn), however, the driver does not wait for the device to provide the response. b. Eventually, the device responds, and the driver provides the tcpsn within the resync packet to KTLS. Now, KTLS can check the tcpsn against any processed TLS records within packet P, and also against any record that is processed in the future within packet P. The asynchronous resync path simplifies the device driver, as it can save bits on the packet completion (32-bit TCP sequence), and pass this information on an asynchronous command instead. Performance: CPU: Intel(R) Xeon(R) CPU E5-2687W v4 @ 3.00GHz, 24 cores, HT off NIC: ConnectX-6 Dx 100GbE dual port Goodput (app-layer throughput) comparison: +---------------+-------+-------+---------+ | # connections | 1 | 4 | 8 | +---------------+-------+-------+---------+ | SW (Gbps) | 7.26 | 24.70 | 50.30 | +---------------+-------+-------+---------+ | HW (Gbps) | 18.50 | 64.30 | 92.90 | +---------------+-------+-------+---------+ | Speedup | 2.55x | 2.56x | 1.85x * | +---------------+-------+-------+---------+ * After linerate is reached, diff is observed in CPU util ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1078029172
@ -428,6 +428,24 @@ by the driver:
|
||||
which were part of a TLS stream.
|
||||
* ``rx_tls_decrypted_bytes`` - number of TLS payload bytes in RX packets
|
||||
which were successfully decrypted.
|
||||
* ``rx_tls_ctx`` - number of TLS RX HW offload contexts added to device for
|
||||
decryption.
|
||||
* ``rx_tls_del`` - number of TLS RX HW offload contexts deleted from device
|
||||
(connection has finished).
|
||||
* ``rx_tls_resync_req_pkt`` - number of received TLS packets with a resync
|
||||
request.
|
||||
* ``rx_tls_resync_req_start`` - number of times the TLS async resync request
|
||||
was started.
|
||||
* ``rx_tls_resync_req_end`` - number of times the TLS async resync request
|
||||
properly ended with providing the HW tracked tcp-seq.
|
||||
* ``rx_tls_resync_req_skip`` - number of times the TLS async resync request
|
||||
procedure was started by not properly ended.
|
||||
* ``rx_tls_resync_res_ok`` - number of times the TLS resync response call to
|
||||
the driver was successfully handled.
|
||||
* ``rx_tls_resync_res_skip`` - number of times the TLS resync response call to
|
||||
the driver was terminated unsuccessfully.
|
||||
* ``rx_tls_err`` - number of RX packets which were part of a TLS stream
|
||||
but were not decrypted due to unexpected error in the state machine.
|
||||
* ``tx_tls_encrypted_packets`` - number of TX packets passed to the device
|
||||
for encryption of their TLS payload.
|
||||
* ``tx_tls_encrypted_bytes`` - number of TLS payload bytes in TX packets
|
||||
|
@ -173,6 +173,7 @@ config MLX5_TLS
|
||||
config MLX5_EN_TLS
|
||||
bool "TLS cryptography-offload accelaration"
|
||||
depends on MLX5_CORE_EN
|
||||
depends on XPS
|
||||
depends on MLX5_FPGA_TLS || MLX5_TLS
|
||||
default y
|
||||
help
|
||||
|
@ -74,7 +74,8 @@ mlx5_core-$(CONFIG_MLX5_EN_IPSEC) += en_accel/ipsec.o en_accel/ipsec_rxtx.o \
|
||||
en_accel/ipsec_stats.o
|
||||
|
||||
mlx5_core-$(CONFIG_MLX5_EN_TLS) += en_accel/tls.o en_accel/tls_rxtx.o en_accel/tls_stats.o \
|
||||
en_accel/ktls.o en_accel/ktls_tx.o
|
||||
en_accel/fs_tcp.o en_accel/ktls.o en_accel/ktls_txrx.o \
|
||||
en_accel/ktls_tx.o en_accel/ktls_rx.o
|
||||
|
||||
mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/dr_domain.o steering/dr_table.o \
|
||||
steering/dr_matcher.o steering/dr_rule.o \
|
||||
|
@ -43,9 +43,20 @@ int mlx5_ktls_create_key(struct mlx5_core_dev *mdev,
|
||||
u32 *p_key_id);
|
||||
void mlx5_ktls_destroy_key(struct mlx5_core_dev *mdev, u32 key_id);
|
||||
|
||||
static inline bool mlx5_accel_is_ktls_tx(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
return MLX5_CAP_GEN(mdev, tls_tx);
|
||||
}
|
||||
|
||||
static inline bool mlx5_accel_is_ktls_rx(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
return MLX5_CAP_GEN(mdev, tls_rx);
|
||||
}
|
||||
|
||||
static inline bool mlx5_accel_is_ktls_device(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
if (!MLX5_CAP_GEN(mdev, tls_tx))
|
||||
if (!mlx5_accel_is_ktls_tx(mdev) &&
|
||||
!mlx5_accel_is_ktls_rx(mdev))
|
||||
return false;
|
||||
|
||||
if (!MLX5_CAP_GEN(mdev, log_max_dek))
|
||||
@ -67,6 +78,12 @@ static inline bool mlx5e_ktls_type_check(struct mlx5_core_dev *mdev,
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static inline bool mlx5_accel_is_ktls_tx(struct mlx5_core_dev *mdev)
|
||||
{ return false; }
|
||||
|
||||
static inline bool mlx5_accel_is_ktls_rx(struct mlx5_core_dev *mdev)
|
||||
{ return false; }
|
||||
|
||||
static inline int
|
||||
mlx5_ktls_create_key(struct mlx5_core_dev *mdev,
|
||||
struct tls_crypto_info *crypto_info,
|
||||
|
@ -23,6 +23,9 @@ static const char *const mlx5_rsc_sgmt_name[] = {
|
||||
MLX5_SGMT_STR_ASSING(SX_SLICE_ALL),
|
||||
MLX5_SGMT_STR_ASSING(RDB),
|
||||
MLX5_SGMT_STR_ASSING(RX_SLICE_ALL),
|
||||
MLX5_SGMT_STR_ASSING(PRM_QUERY_QP),
|
||||
MLX5_SGMT_STR_ASSING(PRM_QUERY_CQ),
|
||||
MLX5_SGMT_STR_ASSING(PRM_QUERY_MKEY),
|
||||
};
|
||||
|
||||
struct mlx5_rsc_dump {
|
||||
@ -130,11 +133,13 @@ struct mlx5_rsc_dump_cmd *mlx5_rsc_dump_cmd_create(struct mlx5_core_dev *dev,
|
||||
cmd->mem_size = key->size;
|
||||
return cmd;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_rsc_dump_cmd_create);
|
||||
|
||||
void mlx5_rsc_dump_cmd_destroy(struct mlx5_rsc_dump_cmd *cmd)
|
||||
{
|
||||
kfree(cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_rsc_dump_cmd_destroy);
|
||||
|
||||
int mlx5_rsc_dump_next(struct mlx5_core_dev *dev, struct mlx5_rsc_dump_cmd *cmd,
|
||||
struct page *page, int *size)
|
||||
@ -155,6 +160,7 @@ int mlx5_rsc_dump_next(struct mlx5_core_dev *dev, struct mlx5_rsc_dump_cmd *cmd,
|
||||
|
||||
return more_dump;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_rsc_dump_next);
|
||||
|
||||
#define MLX5_RSC_DUMP_MENU_SEGMENT 0xffff
|
||||
static int mlx5_rsc_dump_menu(struct mlx5_core_dev *dev)
|
||||
|
@ -4,41 +4,10 @@
|
||||
#ifndef __MLX5_RSC_DUMP_H
|
||||
#define __MLX5_RSC_DUMP_H
|
||||
|
||||
#include <linux/mlx5/rsc_dump.h>
|
||||
#include <linux/mlx5/driver.h>
|
||||
#include "mlx5_core.h"
|
||||
|
||||
enum mlx5_sgmt_type {
|
||||
MLX5_SGMT_TYPE_HW_CQPC,
|
||||
MLX5_SGMT_TYPE_HW_SQPC,
|
||||
MLX5_SGMT_TYPE_HW_RQPC,
|
||||
MLX5_SGMT_TYPE_FULL_SRQC,
|
||||
MLX5_SGMT_TYPE_FULL_CQC,
|
||||
MLX5_SGMT_TYPE_FULL_EQC,
|
||||
MLX5_SGMT_TYPE_FULL_QPC,
|
||||
MLX5_SGMT_TYPE_SND_BUFF,
|
||||
MLX5_SGMT_TYPE_RCV_BUFF,
|
||||
MLX5_SGMT_TYPE_SRQ_BUFF,
|
||||
MLX5_SGMT_TYPE_CQ_BUFF,
|
||||
MLX5_SGMT_TYPE_EQ_BUFF,
|
||||
MLX5_SGMT_TYPE_SX_SLICE,
|
||||
MLX5_SGMT_TYPE_SX_SLICE_ALL,
|
||||
MLX5_SGMT_TYPE_RDB,
|
||||
MLX5_SGMT_TYPE_RX_SLICE_ALL,
|
||||
MLX5_SGMT_TYPE_MENU,
|
||||
MLX5_SGMT_TYPE_TERMINATE,
|
||||
|
||||
MLX5_SGMT_TYPE_NUM, /* Keep last */
|
||||
};
|
||||
|
||||
struct mlx5_rsc_key {
|
||||
enum mlx5_sgmt_type rsc;
|
||||
int index1;
|
||||
int index2;
|
||||
int num_of_obj1;
|
||||
int num_of_obj2;
|
||||
int size;
|
||||
};
|
||||
|
||||
#define MLX5_RSC_DUMP_ALL 0xFFFF
|
||||
struct mlx5_rsc_dump_cmd;
|
||||
struct mlx5_rsc_dump;
|
||||
|
@ -191,13 +191,8 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
|
||||
|
||||
struct mlx5e_tx_wqe {
|
||||
struct mlx5_wqe_ctrl_seg ctrl;
|
||||
union {
|
||||
struct {
|
||||
struct mlx5_wqe_eth_seg eth;
|
||||
struct mlx5_wqe_data_seg data[0];
|
||||
};
|
||||
u8 tls_progress_params_ctx[0];
|
||||
};
|
||||
struct mlx5_wqe_eth_seg eth;
|
||||
struct mlx5_wqe_data_seg data[0];
|
||||
};
|
||||
|
||||
struct mlx5e_rx_wqe_ll {
|
||||
@ -213,10 +208,7 @@ struct mlx5e_umr_wqe {
|
||||
struct mlx5_wqe_ctrl_seg ctrl;
|
||||
struct mlx5_wqe_umr_ctrl_seg uctrl;
|
||||
struct mlx5_mkey_seg mkc;
|
||||
union {
|
||||
struct mlx5_mtt inline_mtts[0];
|
||||
u8 tls_static_params_ctx[0];
|
||||
};
|
||||
struct mlx5_mtt inline_mtts[0];
|
||||
};
|
||||
|
||||
extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];
|
||||
@ -271,6 +263,7 @@ enum {
|
||||
MLX5E_RQ_STATE_AM,
|
||||
MLX5E_RQ_STATE_NO_CSUM_COMPLETE,
|
||||
MLX5E_RQ_STATE_CSUM_FULL, /* cqe_csum_full hw bit is set */
|
||||
MLX5E_RQ_STATE_FPGA_TLS, /* FPGA TLS enabled */
|
||||
};
|
||||
|
||||
struct mlx5e_cq {
|
||||
@ -651,9 +644,11 @@ struct mlx5e_channel {
|
||||
/* AF_XDP zero-copy */
|
||||
struct mlx5e_rq xskrq;
|
||||
struct mlx5e_xdpsq xsksq;
|
||||
struct mlx5e_icosq xskicosq;
|
||||
/* xskicosq can be accessed from any CPU - the spinlock protects it. */
|
||||
spinlock_t xskicosq_lock;
|
||||
|
||||
/* Async ICOSQ */
|
||||
struct mlx5e_icosq async_icosq;
|
||||
/* async_icosq can be accessed from any CPU - the spinlock protects it. */
|
||||
spinlock_t async_icosq_lock;
|
||||
|
||||
/* data path - accessed per napi poll */
|
||||
struct irq_desc *irq_desc;
|
||||
|
@ -105,11 +105,16 @@ enum mlx5e_tunnel_types {
|
||||
|
||||
bool mlx5e_tunnel_inner_ft_supported(struct mlx5_core_dev *mdev);
|
||||
|
||||
struct mlx5e_ttc_rule {
|
||||
struct mlx5_flow_handle *rule;
|
||||
struct mlx5_flow_destination default_dest;
|
||||
};
|
||||
|
||||
/* L3/L4 traffic type classifier */
|
||||
struct mlx5e_ttc_table {
|
||||
struct mlx5e_flow_table ft;
|
||||
struct mlx5_flow_handle *rules[MLX5E_NUM_TT];
|
||||
struct mlx5_flow_handle *tunnel_rules[MLX5E_NUM_TUNNEL_TT];
|
||||
struct mlx5e_flow_table ft;
|
||||
struct mlx5e_ttc_rule rules[MLX5E_NUM_TT];
|
||||
struct mlx5_flow_handle *tunnel_rules[MLX5E_NUM_TUNNEL_TT];
|
||||
};
|
||||
|
||||
/* NIC prio FTS */
|
||||
@ -118,6 +123,9 @@ enum {
|
||||
MLX5E_L2_FT_LEVEL,
|
||||
MLX5E_TTC_FT_LEVEL,
|
||||
MLX5E_INNER_TTC_FT_LEVEL,
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
MLX5E_ACCEL_FS_TCP_FT_LEVEL,
|
||||
#endif
|
||||
#ifdef CONFIG_MLX5_EN_ARFS
|
||||
MLX5E_ARFS_FT_LEVEL
|
||||
#endif
|
||||
@ -211,6 +219,10 @@ static inline int mlx5e_arfs_enable(struct mlx5e_priv *priv) { return -EOPNOTSUP
|
||||
static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv) { return -EOPNOTSUPP; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
struct mlx5e_accel_fs_tcp;
|
||||
#endif
|
||||
|
||||
struct mlx5e_flow_steering {
|
||||
struct mlx5_flow_namespace *ns;
|
||||
#ifdef CONFIG_MLX5_EN_RXNFC
|
||||
@ -224,6 +236,9 @@ struct mlx5e_flow_steering {
|
||||
#ifdef CONFIG_MLX5_EN_ARFS
|
||||
struct mlx5e_arfs_tables arfs;
|
||||
#endif
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
struct mlx5e_accel_fs_tcp *accel_tcp;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ttc_params {
|
||||
@ -248,6 +263,11 @@ void mlx5e_destroy_inner_ttc_table(struct mlx5e_priv *priv,
|
||||
struct mlx5e_ttc_table *ttc);
|
||||
|
||||
void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft);
|
||||
int mlx5e_ttc_fwd_dest(struct mlx5e_priv *priv, enum mlx5e_traffic_types type,
|
||||
struct mlx5_flow_destination *new_dest);
|
||||
struct mlx5_flow_destination
|
||||
mlx5e_ttc_get_default_dest(struct mlx5e_priv *priv, enum mlx5e_traffic_types type);
|
||||
int mlx5e_ttc_fwd_default_dest(struct mlx5e_priv *priv, enum mlx5e_traffic_types type);
|
||||
|
||||
void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv);
|
||||
void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv);
|
||||
|
@ -11,18 +11,6 @@ struct mlx5e_xsk_param {
|
||||
u16 chunk_size;
|
||||
};
|
||||
|
||||
struct mlx5e_rq_param {
|
||||
u32 rqc[MLX5_ST_SZ_DW(rqc)];
|
||||
struct mlx5_wq_param wq;
|
||||
struct mlx5e_rq_frags_info frags_info;
|
||||
};
|
||||
|
||||
struct mlx5e_sq_param {
|
||||
u32 sqc[MLX5_ST_SZ_DW(sqc)];
|
||||
struct mlx5_wq_param wq;
|
||||
bool is_mpw;
|
||||
};
|
||||
|
||||
struct mlx5e_cq_param {
|
||||
u32 cqc[MLX5_ST_SZ_DW(cqc)];
|
||||
struct mlx5_wq_param wq;
|
||||
@ -30,14 +18,26 @@ struct mlx5e_cq_param {
|
||||
u8 cq_period_mode;
|
||||
};
|
||||
|
||||
struct mlx5e_rq_param {
|
||||
struct mlx5e_cq_param cqp;
|
||||
u32 rqc[MLX5_ST_SZ_DW(rqc)];
|
||||
struct mlx5_wq_param wq;
|
||||
struct mlx5e_rq_frags_info frags_info;
|
||||
};
|
||||
|
||||
struct mlx5e_sq_param {
|
||||
struct mlx5e_cq_param cqp;
|
||||
u32 sqc[MLX5_ST_SZ_DW(sqc)];
|
||||
struct mlx5_wq_param wq;
|
||||
bool is_mpw;
|
||||
};
|
||||
|
||||
struct mlx5e_channel_param {
|
||||
struct mlx5e_rq_param rq;
|
||||
struct mlx5e_sq_param sq;
|
||||
struct mlx5e_sq_param txq_sq;
|
||||
struct mlx5e_sq_param xdp_sq;
|
||||
struct mlx5e_sq_param icosq;
|
||||
struct mlx5e_cq_param rx_cq;
|
||||
struct mlx5e_cq_param tx_cq;
|
||||
struct mlx5e_cq_param icosq_cq;
|
||||
struct mlx5e_sq_param async_icosq;
|
||||
};
|
||||
|
||||
static inline bool mlx5e_qid_get_ch_if_in_group(struct mlx5e_params *params,
|
||||
|
@ -11,6 +11,11 @@
|
||||
enum mlx5e_icosq_wqe_type {
|
||||
MLX5E_ICOSQ_WQE_NOP,
|
||||
MLX5E_ICOSQ_WQE_UMR_RX,
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
MLX5E_ICOSQ_WQE_UMR_TLS,
|
||||
MLX5E_ICOSQ_WQE_SET_PSV_TLS,
|
||||
MLX5E_ICOSQ_WQE_GET_PSV_TLS,
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline bool
|
||||
@ -114,9 +119,19 @@ struct mlx5e_icosq_wqe_info {
|
||||
struct {
|
||||
struct mlx5e_rq *rq;
|
||||
} umr;
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
struct {
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
} tls_set_params;
|
||||
struct {
|
||||
struct mlx5e_ktls_rx_resync_buf *buf;
|
||||
} tls_get_params;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
void mlx5e_free_icosq_descs(struct mlx5e_icosq *sq);
|
||||
|
||||
static inline u16 mlx5e_icosq_get_next_pi(struct mlx5e_icosq *sq, u16 size)
|
||||
{
|
||||
struct mlx5_wq_cyc *wq = &sq->wq;
|
||||
@ -182,7 +197,7 @@ mlx5e_notify_hw(struct mlx5_wq_cyc *wq, u16 pc, void __iomem *uar_map,
|
||||
|
||||
static inline bool mlx5e_transport_inline_tx_wqe(struct mlx5_wqe_ctrl_seg *cseg)
|
||||
{
|
||||
return cseg && !!cseg->tisn;
|
||||
return cseg && !!cseg->tis_tir_num;
|
||||
}
|
||||
|
||||
static inline u8
|
||||
|
@ -34,31 +34,13 @@ bool mlx5e_validate_xsk_param(struct mlx5e_params *params,
|
||||
}
|
||||
}
|
||||
|
||||
static void mlx5e_build_xskicosq_param(struct mlx5e_priv *priv,
|
||||
u8 log_wq_size,
|
||||
struct mlx5e_sq_param *param)
|
||||
{
|
||||
void *sqc = param->sqc;
|
||||
void *wq = MLX5_ADDR_OF(sqc, sqc, wq);
|
||||
|
||||
mlx5e_build_sq_param_common(priv, param);
|
||||
|
||||
MLX5_SET(wq, wq, log_wq_sz, log_wq_size);
|
||||
}
|
||||
|
||||
static void mlx5e_build_xsk_cparam(struct mlx5e_priv *priv,
|
||||
struct mlx5e_params *params,
|
||||
struct mlx5e_xsk_param *xsk,
|
||||
struct mlx5e_channel_param *cparam)
|
||||
{
|
||||
const u8 xskicosq_size = MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
|
||||
|
||||
mlx5e_build_rq_param(priv, params, xsk, &cparam->rq);
|
||||
mlx5e_build_xdpsq_param(priv, params, &cparam->xdp_sq);
|
||||
mlx5e_build_xskicosq_param(priv, xskicosq_size, &cparam->icosq);
|
||||
mlx5e_build_rx_cq_param(priv, params, xsk, &cparam->rx_cq);
|
||||
mlx5e_build_tx_cq_param(priv, params, &cparam->tx_cq);
|
||||
mlx5e_build_ico_cq_param(priv, xskicosq_size, &cparam->icosq_cq);
|
||||
}
|
||||
|
||||
int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params,
|
||||
@ -66,7 +48,6 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params,
|
||||
struct mlx5e_channel *c)
|
||||
{
|
||||
struct mlx5e_channel_param *cparam;
|
||||
struct dim_cq_moder icocq_moder = {};
|
||||
int err;
|
||||
|
||||
if (!mlx5e_validate_xsk_param(params, xsk, priv->mdev))
|
||||
@ -78,7 +59,7 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params,
|
||||
|
||||
mlx5e_build_xsk_cparam(priv, params, xsk, cparam);
|
||||
|
||||
err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rx_cq, &c->xskrq.cq);
|
||||
err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rq.cqp, &c->xskrq.cq);
|
||||
if (unlikely(err))
|
||||
goto err_free_cparam;
|
||||
|
||||
@ -86,7 +67,7 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params,
|
||||
if (unlikely(err))
|
||||
goto err_close_rx_cq;
|
||||
|
||||
err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam->tx_cq, &c->xsksq.cq);
|
||||
err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &c->xsksq.cq);
|
||||
if (unlikely(err))
|
||||
goto err_close_rq;
|
||||
|
||||
@ -100,31 +81,12 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params,
|
||||
if (unlikely(err))
|
||||
goto err_close_tx_cq;
|
||||
|
||||
err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq_cq, &c->xskicosq.cq);
|
||||
if (unlikely(err))
|
||||
goto err_close_sq;
|
||||
|
||||
/* Create a dedicated SQ for posting NOPs whenever we need an IRQ to be
|
||||
* triggered and NAPI to be called on the correct CPU.
|
||||
*/
|
||||
err = mlx5e_open_icosq(c, params, &cparam->icosq, &c->xskicosq);
|
||||
if (unlikely(err))
|
||||
goto err_close_icocq;
|
||||
|
||||
kvfree(cparam);
|
||||
|
||||
spin_lock_init(&c->xskicosq_lock);
|
||||
|
||||
set_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
|
||||
|
||||
return 0;
|
||||
|
||||
err_close_icocq:
|
||||
mlx5e_close_cq(&c->xskicosq.cq);
|
||||
|
||||
err_close_sq:
|
||||
mlx5e_close_xdpsq(&c->xsksq);
|
||||
|
||||
err_close_tx_cq:
|
||||
mlx5e_close_cq(&c->xsksq.cq);
|
||||
|
||||
@ -148,32 +110,27 @@ void mlx5e_close_xsk(struct mlx5e_channel *c)
|
||||
|
||||
mlx5e_close_rq(&c->xskrq);
|
||||
mlx5e_close_cq(&c->xskrq.cq);
|
||||
mlx5e_close_icosq(&c->xskicosq);
|
||||
mlx5e_close_cq(&c->xskicosq.cq);
|
||||
mlx5e_close_xdpsq(&c->xsksq);
|
||||
mlx5e_close_cq(&c->xsksq.cq);
|
||||
|
||||
memset(&c->xskrq, 0, sizeof(c->xskrq));
|
||||
memset(&c->xsksq, 0, sizeof(c->xsksq));
|
||||
memset(&c->xskicosq, 0, sizeof(c->xskicosq));
|
||||
}
|
||||
|
||||
void mlx5e_activate_xsk(struct mlx5e_channel *c)
|
||||
{
|
||||
mlx5e_activate_icosq(&c->xskicosq);
|
||||
set_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state);
|
||||
/* TX queue is created active. */
|
||||
|
||||
spin_lock(&c->xskicosq_lock);
|
||||
mlx5e_trigger_irq(&c->xskicosq);
|
||||
spin_unlock(&c->xskicosq_lock);
|
||||
spin_lock(&c->async_icosq_lock);
|
||||
mlx5e_trigger_irq(&c->async_icosq);
|
||||
spin_unlock(&c->async_icosq_lock);
|
||||
}
|
||||
|
||||
void mlx5e_deactivate_xsk(struct mlx5e_channel *c)
|
||||
{
|
||||
mlx5e_deactivate_rq(&c->xskrq);
|
||||
/* TX queue is disabled on close. */
|
||||
mlx5e_deactivate_icosq(&c->xskicosq);
|
||||
}
|
||||
|
||||
static int mlx5e_redirect_xsk_rqt(struct mlx5e_priv *priv, u16 ix, u32 rqn)
|
||||
|
@ -26,19 +26,19 @@ int mlx5e_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
|
||||
return -ENXIO;
|
||||
|
||||
if (!napi_if_scheduled_mark_missed(&c->napi)) {
|
||||
/* To avoid WQE overrun, don't post a NOP if XSKICOSQ is not
|
||||
/* To avoid WQE overrun, don't post a NOP if async_icosq is not
|
||||
* active and not polled by NAPI. Return 0, because the upcoming
|
||||
* activate will trigger the IRQ for us.
|
||||
*/
|
||||
if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &c->xskicosq.state)))
|
||||
if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &c->async_icosq.state)))
|
||||
return 0;
|
||||
|
||||
if (test_and_set_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->xskicosq.state))
|
||||
if (test_and_set_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->async_icosq.state))
|
||||
return 0;
|
||||
|
||||
spin_lock(&c->xskicosq_lock);
|
||||
mlx5e_trigger_irq(&c->xskicosq);
|
||||
spin_unlock(&c->xskicosq_lock);
|
||||
spin_lock(&c->async_icosq_lock);
|
||||
mlx5e_trigger_irq(&c->async_icosq);
|
||||
spin_unlock(&c->async_icosq_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "en_accel/ipsec_rxtx.h"
|
||||
#include "en_accel/tls.h"
|
||||
#include "en_accel/tls_rxtx.h"
|
||||
#include "en.h"
|
||||
#include "en/txrx.h"
|
||||
@ -147,4 +148,23 @@ static inline bool mlx5e_accel_tx_finish(struct mlx5e_priv *priv,
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int mlx5e_accel_sk_get_rxq(struct sock *sk)
|
||||
{
|
||||
int rxq = sk_rx_queue_get(sk);
|
||||
|
||||
if (unlikely(rxq == -1))
|
||||
rxq = 0;
|
||||
|
||||
return rxq;
|
||||
}
|
||||
|
||||
static inline int mlx5e_accel_init_rx(struct mlx5e_priv *priv)
|
||||
{
|
||||
return mlx5e_ktls_init_rx(priv);
|
||||
}
|
||||
|
||||
static inline void mlx5e_accel_cleanup_rx(struct mlx5e_priv *priv)
|
||||
{
|
||||
mlx5e_ktls_cleanup_rx(priv);
|
||||
}
|
||||
#endif /* __MLX5E_EN_ACCEL_H__ */
|
||||
|
400
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
Normal file
400
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
Normal file
@ -0,0 +1,400 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include "en_accel/fs_tcp.h"
|
||||
#include "fs_core.h"
|
||||
|
||||
enum accel_fs_tcp_type {
|
||||
ACCEL_FS_IPV4_TCP,
|
||||
ACCEL_FS_IPV6_TCP,
|
||||
ACCEL_FS_TCP_NUM_TYPES,
|
||||
};
|
||||
|
||||
struct mlx5e_accel_fs_tcp {
|
||||
struct mlx5e_flow_table tables[ACCEL_FS_TCP_NUM_TYPES];
|
||||
struct mlx5_flow_handle *default_rules[ACCEL_FS_TCP_NUM_TYPES];
|
||||
};
|
||||
|
||||
static enum mlx5e_traffic_types fs_accel2tt(enum accel_fs_tcp_type i)
|
||||
{
|
||||
switch (i) {
|
||||
case ACCEL_FS_IPV4_TCP:
|
||||
return MLX5E_TT_IPV4_TCP;
|
||||
default: /* ACCEL_FS_IPV6_TCP */
|
||||
return MLX5E_TT_IPV6_TCP;
|
||||
}
|
||||
}
|
||||
|
||||
static void accel_fs_tcp_set_ipv4_flow(struct mlx5_flow_spec *spec, struct sock *sk)
|
||||
{
|
||||
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol);
|
||||
MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_TCP);
|
||||
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_version);
|
||||
MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, 4);
|
||||
memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
|
||||
outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4),
|
||||
&inet_sk(sk)->inet_daddr, 4);
|
||||
memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
|
||||
outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
|
||||
&inet_sk(sk)->inet_rcv_saddr, 4);
|
||||
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
|
||||
outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4);
|
||||
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
|
||||
outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
|
||||
}
|
||||
|
||||
static void accel_fs_tcp_set_ipv6_flow(struct mlx5_flow_spec *spec, struct sock *sk)
|
||||
{
|
||||
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol);
|
||||
MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_TCP);
|
||||
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_version);
|
||||
MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, 6);
|
||||
memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
|
||||
outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6),
|
||||
&sk->sk_v6_daddr, 16);
|
||||
memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
|
||||
outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
|
||||
&inet6_sk(sk)->saddr, 16);
|
||||
memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
|
||||
outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6),
|
||||
0xff, 16);
|
||||
memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
|
||||
outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
|
||||
0xff, 16);
|
||||
}
|
||||
|
||||
void mlx5e_accel_fs_del_sk(struct mlx5_flow_handle *rule)
|
||||
{
|
||||
mlx5_del_flow_rules(rule);
|
||||
}
|
||||
|
||||
struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_priv *priv,
|
||||
struct sock *sk, u32 tirn,
|
||||
uint32_t flow_tag)
|
||||
{
|
||||
struct mlx5_flow_destination dest = {};
|
||||
struct mlx5e_flow_table *ft = NULL;
|
||||
struct mlx5e_accel_fs_tcp *fs_tcp;
|
||||
MLX5_DECLARE_FLOW_ACT(flow_act);
|
||||
struct mlx5_flow_handle *flow;
|
||||
struct mlx5_flow_spec *spec;
|
||||
|
||||
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
fs_tcp = priv->fs.accel_tcp;
|
||||
|
||||
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
|
||||
|
||||
switch (sk->sk_family) {
|
||||
case AF_INET:
|
||||
accel_fs_tcp_set_ipv4_flow(spec, sk);
|
||||
ft = &fs_tcp->tables[ACCEL_FS_IPV4_TCP];
|
||||
mlx5e_dbg(HW, priv, "%s flow is %pI4:%d -> %pI4:%d\n", __func__,
|
||||
&inet_sk(sk)->inet_rcv_saddr,
|
||||
inet_sk(sk)->inet_sport,
|
||||
&inet_sk(sk)->inet_daddr,
|
||||
inet_sk(sk)->inet_dport);
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
case AF_INET6:
|
||||
if (!sk->sk_ipv6only &&
|
||||
ipv6_addr_type(&sk->sk_v6_daddr) == IPV6_ADDR_MAPPED) {
|
||||
accel_fs_tcp_set_ipv4_flow(spec, sk);
|
||||
ft = &fs_tcp->tables[ACCEL_FS_IPV4_TCP];
|
||||
} else {
|
||||
accel_fs_tcp_set_ipv6_flow(spec, sk);
|
||||
ft = &fs_tcp->tables[ACCEL_FS_IPV6_TCP];
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ft) {
|
||||
flow = ERR_PTR(-EINVAL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
|
||||
outer_headers.tcp_dport);
|
||||
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
|
||||
outer_headers.tcp_sport);
|
||||
MLX5_SET(fte_match_param, spec->match_value, outer_headers.tcp_dport,
|
||||
ntohs(inet_sk(sk)->inet_sport));
|
||||
MLX5_SET(fte_match_param, spec->match_value, outer_headers.tcp_sport,
|
||||
ntohs(inet_sk(sk)->inet_dport));
|
||||
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
|
||||
dest.tir_num = tirn;
|
||||
if (flow_tag != MLX5_FS_DEFAULT_FLOW_TAG) {
|
||||
spec->flow_context.flow_tag = flow_tag;
|
||||
spec->flow_context.flags = FLOW_CONTEXT_HAS_TAG;
|
||||
}
|
||||
|
||||
flow = mlx5_add_flow_rules(ft->t, spec, &flow_act, &dest, 1);
|
||||
|
||||
if (IS_ERR(flow))
|
||||
netdev_err(priv->netdev, "mlx5_add_flow_rules() failed, flow is %ld\n",
|
||||
PTR_ERR(flow));
|
||||
|
||||
out:
|
||||
kvfree(spec);
|
||||
return flow;
|
||||
}
|
||||
|
||||
static int accel_fs_tcp_add_default_rule(struct mlx5e_priv *priv,
|
||||
enum accel_fs_tcp_type type)
|
||||
{
|
||||
struct mlx5e_flow_table *accel_fs_t;
|
||||
struct mlx5_flow_destination dest;
|
||||
struct mlx5e_accel_fs_tcp *fs_tcp;
|
||||
MLX5_DECLARE_FLOW_ACT(flow_act);
|
||||
struct mlx5_flow_handle *rule;
|
||||
int err = 0;
|
||||
|
||||
fs_tcp = priv->fs.accel_tcp;
|
||||
accel_fs_t = &fs_tcp->tables[type];
|
||||
|
||||
dest = mlx5e_ttc_get_default_dest(priv, fs_accel2tt(type));
|
||||
rule = mlx5_add_flow_rules(accel_fs_t->t, NULL, &flow_act, &dest, 1);
|
||||
if (IS_ERR(rule)) {
|
||||
err = PTR_ERR(rule);
|
||||
netdev_err(priv->netdev,
|
||||
"%s: add default rule failed, accel_fs type=%d, err %d\n",
|
||||
__func__, type, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
fs_tcp->default_rules[type] = rule;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MLX5E_ACCEL_FS_TCP_NUM_GROUPS (2)
|
||||
#define MLX5E_ACCEL_FS_TCP_GROUP1_SIZE (BIT(16) - 1)
|
||||
#define MLX5E_ACCEL_FS_TCP_GROUP2_SIZE (BIT(0))
|
||||
#define MLX5E_ACCEL_FS_TCP_TABLE_SIZE (MLX5E_ACCEL_FS_TCP_GROUP1_SIZE +\
|
||||
MLX5E_ACCEL_FS_TCP_GROUP2_SIZE)
|
||||
static int accel_fs_tcp_create_groups(struct mlx5e_flow_table *ft,
|
||||
enum accel_fs_tcp_type type)
|
||||
{
|
||||
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
|
||||
void *outer_headers_c;
|
||||
int ix = 0;
|
||||
u32 *in;
|
||||
int err;
|
||||
u8 *mc;
|
||||
|
||||
ft->g = kcalloc(MLX5E_ACCEL_FS_TCP_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL);
|
||||
in = kvzalloc(inlen, GFP_KERNEL);
|
||||
if (!in || !ft->g) {
|
||||
kvfree(ft->g);
|
||||
kvfree(in);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
|
||||
outer_headers_c = MLX5_ADDR_OF(fte_match_param, mc, outer_headers);
|
||||
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol);
|
||||
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_version);
|
||||
|
||||
switch (type) {
|
||||
case ACCEL_FS_IPV4_TCP:
|
||||
case ACCEL_FS_IPV6_TCP:
|
||||
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, tcp_dport);
|
||||
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, tcp_sport);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ACCEL_FS_IPV4_TCP:
|
||||
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c,
|
||||
src_ipv4_src_ipv6.ipv4_layout.ipv4);
|
||||
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c,
|
||||
dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
|
||||
break;
|
||||
case ACCEL_FS_IPV6_TCP:
|
||||
memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
|
||||
src_ipv4_src_ipv6.ipv6_layout.ipv6),
|
||||
0xff, 16);
|
||||
memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
|
||||
dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
|
||||
0xff, 16);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
|
||||
MLX5_SET_CFG(in, start_flow_index, ix);
|
||||
ix += MLX5E_ACCEL_FS_TCP_GROUP1_SIZE;
|
||||
MLX5_SET_CFG(in, end_flow_index, ix - 1);
|
||||
ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
|
||||
if (IS_ERR(ft->g[ft->num_groups]))
|
||||
goto err;
|
||||
ft->num_groups++;
|
||||
|
||||
/* Default Flow Group */
|
||||
memset(in, 0, inlen);
|
||||
MLX5_SET_CFG(in, start_flow_index, ix);
|
||||
ix += MLX5E_ACCEL_FS_TCP_GROUP2_SIZE;
|
||||
MLX5_SET_CFG(in, end_flow_index, ix - 1);
|
||||
ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
|
||||
if (IS_ERR(ft->g[ft->num_groups]))
|
||||
goto err;
|
||||
ft->num_groups++;
|
||||
|
||||
kvfree(in);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
err = PTR_ERR(ft->g[ft->num_groups]);
|
||||
ft->g[ft->num_groups] = NULL;
|
||||
out:
|
||||
kvfree(in);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int accel_fs_tcp_create_table(struct mlx5e_priv *priv, enum accel_fs_tcp_type type)
|
||||
{
|
||||
struct mlx5e_flow_table *ft = &priv->fs.accel_tcp->tables[type];
|
||||
struct mlx5_flow_table_attr ft_attr = {};
|
||||
int err;
|
||||
|
||||
ft->num_groups = 0;
|
||||
|
||||
ft_attr.max_fte = MLX5E_ACCEL_FS_TCP_TABLE_SIZE;
|
||||
ft_attr.level = MLX5E_ACCEL_FS_TCP_FT_LEVEL;
|
||||
ft_attr.prio = MLX5E_NIC_PRIO;
|
||||
|
||||
ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);
|
||||
if (IS_ERR(ft->t)) {
|
||||
err = PTR_ERR(ft->t);
|
||||
ft->t = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
netdev_dbg(priv->netdev, "Created fs accel table id %u level %u\n",
|
||||
ft->t->id, ft->t->level);
|
||||
|
||||
err = accel_fs_tcp_create_groups(ft, type);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = accel_fs_tcp_add_default_rule(priv, type);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mlx5e_destroy_flow_table(ft);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int accel_fs_tcp_disable(struct mlx5e_priv *priv)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++) {
|
||||
/* Modify ttc rules destination to point back to the indir TIRs */
|
||||
err = mlx5e_ttc_fwd_default_dest(priv, fs_accel2tt(i));
|
||||
if (err) {
|
||||
netdev_err(priv->netdev,
|
||||
"%s: modify ttc[%d] default destination failed, err(%d)\n",
|
||||
__func__, fs_accel2tt(i), err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int accel_fs_tcp_enable(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5_flow_destination dest = {};
|
||||
int err, i;
|
||||
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||
for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++) {
|
||||
dest.ft = priv->fs.accel_tcp->tables[i].t;
|
||||
|
||||
/* Modify ttc rules destination to point on the accel_fs FTs */
|
||||
err = mlx5e_ttc_fwd_dest(priv, fs_accel2tt(i), &dest);
|
||||
if (err) {
|
||||
netdev_err(priv->netdev,
|
||||
"%s: modify ttc[%d] destination to accel failed, err(%d)\n",
|
||||
__func__, fs_accel2tt(i), err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void accel_fs_tcp_destroy_table(struct mlx5e_priv *priv, int i)
|
||||
{
|
||||
struct mlx5e_accel_fs_tcp *fs_tcp;
|
||||
|
||||
fs_tcp = priv->fs.accel_tcp;
|
||||
if (IS_ERR_OR_NULL(fs_tcp->tables[i].t))
|
||||
return;
|
||||
|
||||
mlx5_del_flow_rules(fs_tcp->default_rules[i]);
|
||||
mlx5e_destroy_flow_table(&fs_tcp->tables[i]);
|
||||
fs_tcp->tables[i].t = NULL;
|
||||
}
|
||||
|
||||
void mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!priv->fs.accel_tcp)
|
||||
return;
|
||||
|
||||
accel_fs_tcp_disable(priv);
|
||||
|
||||
for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++)
|
||||
accel_fs_tcp_destroy_table(priv, i);
|
||||
|
||||
kfree(priv->fs.accel_tcp);
|
||||
priv->fs.accel_tcp = NULL;
|
||||
}
|
||||
|
||||
int mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
if (!MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ft_field_support.outer_ip_version))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
priv->fs.accel_tcp = kzalloc(sizeof(*priv->fs.accel_tcp), GFP_KERNEL);
|
||||
if (!priv->fs.accel_tcp)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++) {
|
||||
err = accel_fs_tcp_create_table(priv, i);
|
||||
if (err)
|
||||
goto err_destroy_tables;
|
||||
}
|
||||
|
||||
err = accel_fs_tcp_enable(priv);
|
||||
if (err)
|
||||
goto err_destroy_tables;
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_tables:
|
||||
while (--i >= 0)
|
||||
accel_fs_tcp_destroy_table(priv, i);
|
||||
|
||||
kfree(priv->fs.accel_tcp);
|
||||
priv->fs.accel_tcp = NULL;
|
||||
return err;
|
||||
}
|
27
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.h
Normal file
27
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */
|
||||
|
||||
#ifndef __MLX5E_ACCEL_FS_TCP_H__
|
||||
#define __MLX5E_ACCEL_FS_TCP_H__
|
||||
|
||||
#include "en.h"
|
||||
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
int mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv);
|
||||
void mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *priv);
|
||||
struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_priv *priv,
|
||||
struct sock *sk, u32 tirn,
|
||||
uint32_t flow_tag);
|
||||
void mlx5e_accel_fs_del_sk(struct mlx5_flow_handle *rule);
|
||||
#else
|
||||
static inline int mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv) { return 0; }
|
||||
static inline void mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *priv) {}
|
||||
static inline struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_priv *priv,
|
||||
struct sock *sk, u32 tirn,
|
||||
uint32_t flow_tag)
|
||||
{ return ERR_PTR(-EOPNOTSUPP); }
|
||||
static inline void mlx5e_accel_fs_del_sk(struct mlx5_flow_handle *rule) {}
|
||||
#endif
|
||||
|
||||
#endif /* __MLX5E_ACCEL_FS_TCP_H__ */
|
||||
|
@ -3,31 +3,8 @@
|
||||
|
||||
#include "en.h"
|
||||
#include "en_accel/ktls.h"
|
||||
|
||||
u16 mlx5e_ktls_get_stop_room(struct mlx5e_txqsq *sq)
|
||||
{
|
||||
u16 num_dumps, stop_room = 0;
|
||||
|
||||
num_dumps = mlx5e_ktls_dumps_num_wqes(sq, MAX_SKB_FRAGS, TLS_MAX_PAYLOAD_SIZE);
|
||||
|
||||
stop_room += mlx5e_stop_room_for_wqe(MLX5E_KTLS_STATIC_WQEBBS);
|
||||
stop_room += mlx5e_stop_room_for_wqe(MLX5E_KTLS_PROGRESS_WQEBBS);
|
||||
stop_room += num_dumps * mlx5e_stop_room_for_wqe(MLX5E_KTLS_DUMP_WQEBBS);
|
||||
|
||||
return stop_room;
|
||||
}
|
||||
|
||||
static int mlx5e_ktls_create_tis(struct mlx5_core_dev *mdev, u32 *tisn)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {};
|
||||
void *tisc;
|
||||
|
||||
tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
|
||||
|
||||
MLX5_SET(tisc, tisc, tls_en, 1);
|
||||
|
||||
return mlx5e_create_tis(mdev, in, tisn);
|
||||
}
|
||||
#include "en_accel/ktls_utils.h"
|
||||
#include "en_accel/fs_tcp.h"
|
||||
|
||||
static int mlx5e_ktls_add(struct net_device *netdev, struct sock *sk,
|
||||
enum tls_offload_ctx_dir direction,
|
||||
@ -35,42 +12,17 @@ static int mlx5e_ktls_add(struct net_device *netdev, struct sock *sk,
|
||||
u32 start_offload_tcp_sn)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5e_ktls_offload_context_tx *tx_priv;
|
||||
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(direction != TLS_OFFLOAD_CTX_DIR_TX))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(!mlx5e_ktls_type_check(mdev, crypto_info)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
tx_priv = kvzalloc(sizeof(*tx_priv), GFP_KERNEL);
|
||||
if (!tx_priv)
|
||||
return -ENOMEM;
|
||||
if (direction == TLS_OFFLOAD_CTX_DIR_TX)
|
||||
err = mlx5e_ktls_add_tx(netdev, sk, crypto_info, start_offload_tcp_sn);
|
||||
else
|
||||
err = mlx5e_ktls_add_rx(netdev, sk, crypto_info, start_offload_tcp_sn);
|
||||
|
||||
tx_priv->expected_seq = start_offload_tcp_sn;
|
||||
tx_priv->crypto_info = *(struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
|
||||
mlx5e_set_ktls_tx_priv_ctx(tls_ctx, tx_priv);
|
||||
|
||||
/* tc and underlay_qpn values are not in use for tls tis */
|
||||
err = mlx5e_ktls_create_tis(mdev, &tx_priv->tisn);
|
||||
if (err)
|
||||
goto create_tis_fail;
|
||||
|
||||
err = mlx5_ktls_create_key(mdev, crypto_info, &tx_priv->key_id);
|
||||
if (err)
|
||||
goto encryption_key_create_fail;
|
||||
|
||||
mlx5e_ktls_tx_offload_set_pending(tx_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
encryption_key_create_fail:
|
||||
mlx5e_destroy_tis(priv->mdev, tx_priv->tisn);
|
||||
create_tis_fail:
|
||||
kvfree(tx_priv);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -78,29 +30,72 @@ static void mlx5e_ktls_del(struct net_device *netdev,
|
||||
struct tls_context *tls_ctx,
|
||||
enum tls_offload_ctx_dir direction)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5e_ktls_offload_context_tx *tx_priv =
|
||||
mlx5e_get_ktls_tx_priv_ctx(tls_ctx);
|
||||
if (direction == TLS_OFFLOAD_CTX_DIR_TX)
|
||||
mlx5e_ktls_del_tx(netdev, tls_ctx);
|
||||
else
|
||||
mlx5e_ktls_del_rx(netdev, tls_ctx);
|
||||
}
|
||||
|
||||
mlx5e_destroy_tis(priv->mdev, tx_priv->tisn);
|
||||
mlx5_ktls_destroy_key(priv->mdev, tx_priv->key_id);
|
||||
kvfree(tx_priv);
|
||||
static int mlx5e_ktls_resync(struct net_device *netdev,
|
||||
struct sock *sk, u32 seq, u8 *rcd_sn,
|
||||
enum tls_offload_ctx_dir direction)
|
||||
{
|
||||
if (unlikely(direction != TLS_OFFLOAD_CTX_DIR_RX))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mlx5e_ktls_rx_resync(netdev, sk, seq, rcd_sn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct tlsdev_ops mlx5e_ktls_ops = {
|
||||
.tls_dev_add = mlx5e_ktls_add,
|
||||
.tls_dev_del = mlx5e_ktls_del,
|
||||
.tls_dev_resync = mlx5e_ktls_resync,
|
||||
};
|
||||
|
||||
void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
if (!mlx5_accel_is_ktls_device(priv->mdev))
|
||||
return;
|
||||
if (mlx5_accel_is_ktls_tx(mdev)) {
|
||||
netdev->hw_features |= NETIF_F_HW_TLS_TX;
|
||||
netdev->features |= NETIF_F_HW_TLS_TX;
|
||||
}
|
||||
|
||||
netdev->hw_features |= NETIF_F_HW_TLS_TX;
|
||||
netdev->features |= NETIF_F_HW_TLS_TX;
|
||||
if (mlx5_accel_is_ktls_rx(mdev))
|
||||
netdev->hw_features |= NETIF_F_HW_TLS_RX;
|
||||
|
||||
netdev->tlsdev_ops = &mlx5e_ktls_ops;
|
||||
}
|
||||
|
||||
int mlx5e_ktls_set_feature_rx(struct net_device *netdev, bool enable)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
if (enable)
|
||||
err = mlx5e_accel_fs_tcp_create(priv);
|
||||
else
|
||||
mlx5e_accel_fs_tcp_destroy(priv);
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5e_ktls_init_rx(struct mlx5e_priv *priv)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (priv->netdev->features & NETIF_F_HW_TLS_RX)
|
||||
err = mlx5e_accel_fs_tcp_create(priv);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5e_ktls_cleanup_rx(struct mlx5e_priv *priv)
|
||||
{
|
||||
if (priv->netdev->features & NETIF_F_HW_TLS_RX)
|
||||
mlx5e_accel_fs_tcp_destroy(priv);
|
||||
}
|
||||
|
@ -7,122 +7,32 @@
|
||||
#include "en.h"
|
||||
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
#include <net/tls.h>
|
||||
#include "accel/tls.h"
|
||||
#include "en_accel/tls_rxtx.h"
|
||||
|
||||
#define MLX5E_KTLS_STATIC_UMR_WQE_SZ \
|
||||
(offsetof(struct mlx5e_umr_wqe, tls_static_params_ctx) + \
|
||||
MLX5_ST_SZ_BYTES(tls_static_params))
|
||||
#define MLX5E_KTLS_STATIC_WQEBBS \
|
||||
(DIV_ROUND_UP(MLX5E_KTLS_STATIC_UMR_WQE_SZ, MLX5_SEND_WQE_BB))
|
||||
|
||||
#define MLX5E_KTLS_PROGRESS_WQE_SZ \
|
||||
(offsetof(struct mlx5e_tx_wqe, tls_progress_params_ctx) + \
|
||||
MLX5_ST_SZ_BYTES(tls_progress_params))
|
||||
#define MLX5E_KTLS_PROGRESS_WQEBBS \
|
||||
(DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_BB))
|
||||
|
||||
struct mlx5e_dump_wqe {
|
||||
struct mlx5_wqe_ctrl_seg ctrl;
|
||||
struct mlx5_wqe_data_seg data;
|
||||
};
|
||||
|
||||
#define MLX5E_TLS_FETCH_UMR_WQE(sq, pi) \
|
||||
((struct mlx5e_umr_wqe *)mlx5e_fetch_wqe(&(sq)->wq, pi, MLX5E_KTLS_STATIC_UMR_WQE_SZ))
|
||||
#define MLX5E_TLS_FETCH_PROGRESS_WQE(sq, pi) \
|
||||
((struct mlx5e_tx_wqe *)mlx5e_fetch_wqe(&(sq)->wq, pi, MLX5E_KTLS_PROGRESS_WQE_SZ))
|
||||
#define MLX5E_TLS_FETCH_DUMP_WQE(sq, pi) \
|
||||
((struct mlx5e_dump_wqe *)mlx5e_fetch_wqe(&(sq)->wq, pi, \
|
||||
sizeof(struct mlx5e_dump_wqe)))
|
||||
|
||||
#define MLX5E_KTLS_DUMP_WQEBBS \
|
||||
(DIV_ROUND_UP(sizeof(struct mlx5e_dump_wqe), MLX5_SEND_WQE_BB))
|
||||
|
||||
enum {
|
||||
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD = 0,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_OFFLOAD = 1,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_AUTHENTICATION = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START = 0,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING = 1,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING = 2,
|
||||
};
|
||||
|
||||
struct mlx5e_ktls_offload_context_tx {
|
||||
struct tls_offload_context_tx *tx_ctx;
|
||||
struct tls12_crypto_info_aes_gcm_128 crypto_info;
|
||||
u32 expected_seq;
|
||||
u32 tisn;
|
||||
u32 key_id;
|
||||
bool ctx_post_pending;
|
||||
};
|
||||
|
||||
struct mlx5e_ktls_offload_context_tx_shadow {
|
||||
struct tls_offload_context_tx tx_ctx;
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx;
|
||||
};
|
||||
|
||||
static inline void
|
||||
mlx5e_set_ktls_tx_priv_ctx(struct tls_context *tls_ctx,
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx)
|
||||
{
|
||||
struct tls_offload_context_tx *tx_ctx = tls_offload_ctx_tx(tls_ctx);
|
||||
struct mlx5e_ktls_offload_context_tx_shadow *shadow;
|
||||
|
||||
BUILD_BUG_ON(sizeof(*shadow) > TLS_OFFLOAD_CONTEXT_SIZE_TX);
|
||||
|
||||
shadow = (struct mlx5e_ktls_offload_context_tx_shadow *)tx_ctx;
|
||||
|
||||
shadow->priv_tx = priv_tx;
|
||||
priv_tx->tx_ctx = tx_ctx;
|
||||
}
|
||||
|
||||
static inline struct mlx5e_ktls_offload_context_tx *
|
||||
mlx5e_get_ktls_tx_priv_ctx(struct tls_context *tls_ctx)
|
||||
{
|
||||
struct tls_offload_context_tx *tx_ctx = tls_offload_ctx_tx(tls_ctx);
|
||||
struct mlx5e_ktls_offload_context_tx_shadow *shadow;
|
||||
|
||||
BUILD_BUG_ON(sizeof(*shadow) > TLS_OFFLOAD_CONTEXT_SIZE_TX);
|
||||
|
||||
shadow = (struct mlx5e_ktls_offload_context_tx_shadow *)tx_ctx;
|
||||
|
||||
return shadow->priv_tx;
|
||||
}
|
||||
|
||||
void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv);
|
||||
void mlx5e_ktls_tx_offload_set_pending(struct mlx5e_ktls_offload_context_tx *priv_tx);
|
||||
|
||||
bool mlx5e_ktls_handle_tx_skb(struct tls_context *tls_ctx, struct mlx5e_txqsq *sq,
|
||||
struct sk_buff *skb, int datalen,
|
||||
struct mlx5e_accel_tx_tls_state *state);
|
||||
void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
|
||||
struct mlx5e_tx_wqe_info *wi,
|
||||
u32 *dma_fifo_cc);
|
||||
u16 mlx5e_ktls_get_stop_room(struct mlx5e_txqsq *sq);
|
||||
|
||||
static inline u8
|
||||
mlx5e_ktls_dumps_num_wqes(struct mlx5e_txqsq *sq, unsigned int nfrags,
|
||||
unsigned int sync_len)
|
||||
{
|
||||
/* Given the MTU and sync_len, calculates an upper bound for the
|
||||
* number of DUMP WQEs needed for the TX resync of a record.
|
||||
*/
|
||||
return nfrags + DIV_ROUND_UP(sync_len, sq->hw_mtu);
|
||||
}
|
||||
int mlx5e_ktls_init_rx(struct mlx5e_priv *priv);
|
||||
void mlx5e_ktls_cleanup_rx(struct mlx5e_priv *priv);
|
||||
int mlx5e_ktls_set_feature_rx(struct net_device *netdev, bool enable);
|
||||
#else
|
||||
|
||||
static inline void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
|
||||
struct mlx5e_tx_wqe_info *wi,
|
||||
u32 *dma_fifo_cc) {}
|
||||
static inline int mlx5e_ktls_init_rx(struct mlx5e_priv *priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mlx5e_ktls_cleanup_rx(struct mlx5e_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mlx5e_ktls_set_feature_rx(struct net_device *netdev, bool enable)
|
||||
{
|
||||
netdev_warn(netdev, "kTLS is not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __MLX5E_TLS_H__ */
|
||||
|
670
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c
Normal file
670
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c
Normal file
@ -0,0 +1,670 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
// Copyright (c) 2019 Mellanox Technologies.
|
||||
|
||||
#include <net/inet6_hashtables.h>
|
||||
#include "en_accel/en_accel.h"
|
||||
#include "en_accel/tls.h"
|
||||
#include "en_accel/ktls_txrx.h"
|
||||
#include "en_accel/ktls_utils.h"
|
||||
#include "en_accel/fs_tcp.h"
|
||||
|
||||
struct accel_rule {
|
||||
struct work_struct work;
|
||||
struct mlx5e_priv *priv;
|
||||
struct mlx5_flow_handle *rule;
|
||||
};
|
||||
|
||||
#define PROGRESS_PARAMS_WRITE_UNIT 64
|
||||
#define PROGRESS_PARAMS_PADDED_SIZE \
|
||||
(ALIGN(sizeof(struct mlx5_wqe_tls_progress_params_seg), \
|
||||
PROGRESS_PARAMS_WRITE_UNIT))
|
||||
|
||||
struct mlx5e_ktls_rx_resync_buf {
|
||||
union {
|
||||
struct mlx5_wqe_tls_progress_params_seg progress;
|
||||
u8 pad[PROGRESS_PARAMS_PADDED_SIZE];
|
||||
} ____cacheline_aligned_in_smp;
|
||||
dma_addr_t dma_addr;
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5E_PRIV_RX_FLAG_DELETING,
|
||||
MLX5E_NUM_PRIV_RX_FLAGS,
|
||||
};
|
||||
|
||||
struct mlx5e_ktls_rx_resync_ctx {
|
||||
struct tls_offload_resync_async core;
|
||||
struct work_struct work;
|
||||
struct mlx5e_priv *priv;
|
||||
refcount_t refcnt;
|
||||
__be64 sw_rcd_sn_be;
|
||||
u32 seq;
|
||||
};
|
||||
|
||||
struct mlx5e_ktls_offload_context_rx {
|
||||
struct tls12_crypto_info_aes_gcm_128 crypto_info;
|
||||
struct accel_rule rule;
|
||||
struct sock *sk;
|
||||
struct mlx5e_rq_stats *stats;
|
||||
struct completion add_ctx;
|
||||
u32 tirn;
|
||||
u32 key_id;
|
||||
u32 rxq;
|
||||
DECLARE_BITMAP(flags, MLX5E_NUM_PRIV_RX_FLAGS);
|
||||
|
||||
/* resync */
|
||||
struct mlx5e_ktls_rx_resync_ctx resync;
|
||||
};
|
||||
|
||||
static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, u32 *tirn, u32 rqtn)
|
||||
{
|
||||
int err, inlen;
|
||||
void *tirc;
|
||||
u32 *in;
|
||||
|
||||
inlen = MLX5_ST_SZ_BYTES(create_tir_in);
|
||||
in = kvzalloc(inlen, GFP_KERNEL);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
||||
tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
|
||||
|
||||
MLX5_SET(tirc, tirc, transport_domain, mdev->mlx5e_res.td.tdn);
|
||||
MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
|
||||
MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
|
||||
MLX5_SET(tirc, tirc, indirect_table, rqtn);
|
||||
MLX5_SET(tirc, tirc, tls_en, 1);
|
||||
MLX5_SET(tirc, tirc, self_lb_block,
|
||||
MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST |
|
||||
MLX5_TIRC_SELF_LB_BLOCK_BLOCK_MULTICAST);
|
||||
|
||||
err = mlx5_core_create_tir(mdev, in, tirn);
|
||||
|
||||
kvfree(in);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void accel_rule_handle_work(struct work_struct *work)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
struct accel_rule *accel_rule;
|
||||
struct mlx5_flow_handle *rule;
|
||||
|
||||
accel_rule = container_of(work, struct accel_rule, work);
|
||||
priv_rx = container_of(accel_rule, struct mlx5e_ktls_offload_context_rx, rule);
|
||||
if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags)))
|
||||
goto out;
|
||||
|
||||
rule = mlx5e_accel_fs_add_sk(accel_rule->priv, priv_rx->sk,
|
||||
priv_rx->tirn, MLX5_FS_DEFAULT_FLOW_TAG);
|
||||
if (!IS_ERR_OR_NULL(rule))
|
||||
accel_rule->rule = rule;
|
||||
out:
|
||||
complete(&priv_rx->add_ctx);
|
||||
}
|
||||
|
||||
static void accel_rule_init(struct accel_rule *rule, struct mlx5e_priv *priv,
|
||||
struct sock *sk)
|
||||
{
|
||||
INIT_WORK(&rule->work, accel_rule_handle_work);
|
||||
rule->priv = priv;
|
||||
}
|
||||
|
||||
static void icosq_fill_wi(struct mlx5e_icosq *sq, u16 pi,
|
||||
struct mlx5e_icosq_wqe_info *wi)
|
||||
{
|
||||
sq->db.wqe_info[pi] = *wi;
|
||||
}
|
||||
|
||||
static struct mlx5_wqe_ctrl_seg *
|
||||
post_static_params(struct mlx5e_icosq *sq,
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx)
|
||||
{
|
||||
struct mlx5e_set_tls_static_params_wqe *wqe;
|
||||
struct mlx5e_icosq_wqe_info wi;
|
||||
u16 pi, num_wqebbs, room;
|
||||
|
||||
num_wqebbs = MLX5E_TLS_SET_STATIC_PARAMS_WQEBBS;
|
||||
room = mlx5e_stop_room_for_wqe(num_wqebbs);
|
||||
if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, room)))
|
||||
return ERR_PTR(-ENOSPC);
|
||||
|
||||
pi = mlx5e_icosq_get_next_pi(sq, num_wqebbs);
|
||||
wqe = MLX5E_TLS_FETCH_SET_STATIC_PARAMS_WQE(sq, pi);
|
||||
mlx5e_ktls_build_static_params(wqe, sq->pc, sq->sqn, &priv_rx->crypto_info,
|
||||
priv_rx->tirn, priv_rx->key_id,
|
||||
priv_rx->resync.seq, false,
|
||||
TLS_OFFLOAD_CTX_DIR_RX);
|
||||
wi = (struct mlx5e_icosq_wqe_info) {
|
||||
.wqe_type = MLX5E_ICOSQ_WQE_UMR_TLS,
|
||||
.num_wqebbs = num_wqebbs,
|
||||
.tls_set_params.priv_rx = priv_rx,
|
||||
};
|
||||
icosq_fill_wi(sq, pi, &wi);
|
||||
sq->pc += num_wqebbs;
|
||||
|
||||
return &wqe->ctrl;
|
||||
}
|
||||
|
||||
static struct mlx5_wqe_ctrl_seg *
|
||||
post_progress_params(struct mlx5e_icosq *sq,
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx,
|
||||
u32 next_record_tcp_sn)
|
||||
{
|
||||
struct mlx5e_set_tls_progress_params_wqe *wqe;
|
||||
struct mlx5e_icosq_wqe_info wi;
|
||||
u16 pi, num_wqebbs, room;
|
||||
|
||||
num_wqebbs = MLX5E_TLS_SET_PROGRESS_PARAMS_WQEBBS;
|
||||
room = mlx5e_stop_room_for_wqe(num_wqebbs);
|
||||
if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, room)))
|
||||
return ERR_PTR(-ENOSPC);
|
||||
|
||||
pi = mlx5e_icosq_get_next_pi(sq, num_wqebbs);
|
||||
wqe = MLX5E_TLS_FETCH_SET_PROGRESS_PARAMS_WQE(sq, pi);
|
||||
mlx5e_ktls_build_progress_params(wqe, sq->pc, sq->sqn, priv_rx->tirn, false,
|
||||
next_record_tcp_sn,
|
||||
TLS_OFFLOAD_CTX_DIR_RX);
|
||||
wi = (struct mlx5e_icosq_wqe_info) {
|
||||
.wqe_type = MLX5E_ICOSQ_WQE_SET_PSV_TLS,
|
||||
.num_wqebbs = num_wqebbs,
|
||||
.tls_set_params.priv_rx = priv_rx,
|
||||
};
|
||||
|
||||
icosq_fill_wi(sq, pi, &wi);
|
||||
sq->pc += num_wqebbs;
|
||||
|
||||
return &wqe->ctrl;
|
||||
}
|
||||
|
||||
static int post_rx_param_wqes(struct mlx5e_channel *c,
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx,
|
||||
u32 next_record_tcp_sn)
|
||||
{
|
||||
struct mlx5_wqe_ctrl_seg *cseg;
|
||||
struct mlx5e_icosq *sq;
|
||||
int err;
|
||||
|
||||
err = 0;
|
||||
sq = &c->async_icosq;
|
||||
spin_lock(&c->async_icosq_lock);
|
||||
|
||||
cseg = post_static_params(sq, priv_rx);
|
||||
if (IS_ERR(cseg))
|
||||
goto err_out;
|
||||
cseg = post_progress_params(sq, priv_rx, next_record_tcp_sn);
|
||||
if (IS_ERR(cseg))
|
||||
goto err_out;
|
||||
|
||||
mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg);
|
||||
unlock:
|
||||
spin_unlock(&c->async_icosq_lock);
|
||||
|
||||
return err;
|
||||
|
||||
err_out:
|
||||
priv_rx->stats->tls_resync_req_skip++;
|
||||
err = PTR_ERR(cseg);
|
||||
complete(&priv_rx->add_ctx);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5e_set_ktls_rx_priv_ctx(struct tls_context *tls_ctx,
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx **ctx =
|
||||
__tls_driver_ctx(tls_ctx, TLS_OFFLOAD_CTX_DIR_RX);
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct mlx5e_ktls_offload_context_rx *) >
|
||||
TLS_OFFLOAD_CONTEXT_SIZE_RX);
|
||||
|
||||
*ctx = priv_rx;
|
||||
}
|
||||
|
||||
static struct mlx5e_ktls_offload_context_rx *
|
||||
mlx5e_get_ktls_rx_priv_ctx(struct tls_context *tls_ctx)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx **ctx =
|
||||
__tls_driver_ctx(tls_ctx, TLS_OFFLOAD_CTX_DIR_RX);
|
||||
|
||||
return *ctx;
|
||||
}
|
||||
|
||||
/* Re-sync */
|
||||
/* Runs in work context */
|
||||
static struct mlx5_wqe_ctrl_seg *
|
||||
resync_post_get_progress_params(struct mlx5e_icosq *sq,
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx)
|
||||
{
|
||||
struct mlx5e_get_tls_progress_params_wqe *wqe;
|
||||
struct mlx5e_ktls_rx_resync_buf *buf;
|
||||
struct mlx5e_icosq_wqe_info wi;
|
||||
struct mlx5_wqe_ctrl_seg *cseg;
|
||||
struct mlx5_seg_get_psv *psv;
|
||||
struct device *pdev;
|
||||
int err;
|
||||
u16 pi;
|
||||
|
||||
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
|
||||
if (unlikely(!buf)) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
pdev = sq->channel->priv->mdev->device;
|
||||
buf->dma_addr = dma_map_single(pdev, &buf->progress,
|
||||
PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(pdev, buf->dma_addr))) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
buf->priv_rx = priv_rx;
|
||||
|
||||
BUILD_BUG_ON(MLX5E_KTLS_GET_PROGRESS_WQEBBS != 1);
|
||||
if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, 1))) {
|
||||
err = -ENOSPC;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
pi = mlx5e_icosq_get_next_pi(sq, 1);
|
||||
wqe = MLX5E_TLS_FETCH_GET_PROGRESS_PARAMS_WQE(sq, pi);
|
||||
|
||||
#define GET_PSV_DS_CNT (DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS))
|
||||
|
||||
cseg = &wqe->ctrl;
|
||||
cseg->opmod_idx_opcode =
|
||||
cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_GET_PSV |
|
||||
(MLX5_OPC_MOD_TLS_TIR_PROGRESS_PARAMS << 24));
|
||||
cseg->qpn_ds =
|
||||
cpu_to_be32((sq->sqn << MLX5_WQE_CTRL_QPN_SHIFT) | GET_PSV_DS_CNT);
|
||||
|
||||
psv = &wqe->psv;
|
||||
psv->num_psv = 1 << 4;
|
||||
psv->l_key = sq->channel->mkey_be;
|
||||
psv->psv_index[0] = cpu_to_be32(priv_rx->tirn);
|
||||
psv->va = cpu_to_be64(buf->dma_addr);
|
||||
|
||||
wi = (struct mlx5e_icosq_wqe_info) {
|
||||
.wqe_type = MLX5E_ICOSQ_WQE_GET_PSV_TLS,
|
||||
.num_wqebbs = 1,
|
||||
.tls_get_params.buf = buf,
|
||||
};
|
||||
icosq_fill_wi(sq, pi, &wi);
|
||||
sq->pc++;
|
||||
|
||||
return cseg;
|
||||
|
||||
err_out:
|
||||
priv_rx->stats->tls_resync_req_skip++;
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/* Function is called with elevated refcount.
|
||||
* It decreases it only if no WQE is posted.
|
||||
*/
|
||||
static void resync_handle_work(struct work_struct *work)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
struct mlx5e_ktls_rx_resync_ctx *resync;
|
||||
struct mlx5_wqe_ctrl_seg *cseg;
|
||||
struct mlx5e_channel *c;
|
||||
struct mlx5e_icosq *sq;
|
||||
struct mlx5_wq_cyc *wq;
|
||||
|
||||
resync = container_of(work, struct mlx5e_ktls_rx_resync_ctx, work);
|
||||
priv_rx = container_of(resync, struct mlx5e_ktls_offload_context_rx, resync);
|
||||
|
||||
if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) {
|
||||
refcount_dec(&resync->refcnt);
|
||||
return;
|
||||
}
|
||||
|
||||
c = resync->priv->channels.c[priv_rx->rxq];
|
||||
sq = &c->async_icosq;
|
||||
wq = &sq->wq;
|
||||
|
||||
spin_lock(&c->async_icosq_lock);
|
||||
|
||||
cseg = resync_post_get_progress_params(sq, priv_rx);
|
||||
if (IS_ERR(cseg)) {
|
||||
refcount_dec(&resync->refcnt);
|
||||
goto unlock;
|
||||
}
|
||||
mlx5e_notify_hw(wq, sq->pc, sq->uar_map, cseg);
|
||||
unlock:
|
||||
spin_unlock(&c->async_icosq_lock);
|
||||
}
|
||||
|
||||
static void resync_init(struct mlx5e_ktls_rx_resync_ctx *resync,
|
||||
struct mlx5e_priv *priv)
|
||||
{
|
||||
INIT_WORK(&resync->work, resync_handle_work);
|
||||
resync->priv = priv;
|
||||
refcount_set(&resync->refcnt, 1);
|
||||
}
|
||||
|
||||
/* Function can be called with the refcount being either elevated or not.
|
||||
* It does not affect the refcount.
|
||||
*/
|
||||
static int resync_handle_seq_match(struct mlx5e_ktls_offload_context_rx *priv_rx,
|
||||
struct mlx5e_channel *c)
|
||||
{
|
||||
struct tls12_crypto_info_aes_gcm_128 *info = &priv_rx->crypto_info;
|
||||
struct mlx5_wqe_ctrl_seg *cseg;
|
||||
struct mlx5e_icosq *sq;
|
||||
int err;
|
||||
|
||||
memcpy(info->rec_seq, &priv_rx->resync.sw_rcd_sn_be, sizeof(info->rec_seq));
|
||||
err = 0;
|
||||
|
||||
sq = &c->async_icosq;
|
||||
spin_lock(&c->async_icosq_lock);
|
||||
|
||||
cseg = post_static_params(sq, priv_rx);
|
||||
if (IS_ERR(cseg)) {
|
||||
priv_rx->stats->tls_resync_res_skip++;
|
||||
err = PTR_ERR(cseg);
|
||||
goto unlock;
|
||||
}
|
||||
/* Do not increment priv_rx refcnt, CQE handling is empty */
|
||||
mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg);
|
||||
priv_rx->stats->tls_resync_res_ok++;
|
||||
unlock:
|
||||
spin_unlock(&c->async_icosq_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Function is called with elevated refcount, it decreases it. */
|
||||
void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
|
||||
struct mlx5e_icosq *sq)
|
||||
{
|
||||
struct mlx5e_ktls_rx_resync_buf *buf = wi->tls_get_params.buf;
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
struct mlx5e_ktls_rx_resync_ctx *resync;
|
||||
u8 tracker_state, auth_state, *ctx;
|
||||
u32 hw_seq;
|
||||
|
||||
priv_rx = buf->priv_rx;
|
||||
resync = &priv_rx->resync;
|
||||
|
||||
if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags)))
|
||||
goto out;
|
||||
|
||||
dma_sync_single_for_cpu(resync->priv->mdev->device, buf->dma_addr,
|
||||
PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE);
|
||||
|
||||
ctx = buf->progress.ctx;
|
||||
tracker_state = MLX5_GET(tls_progress_params, ctx, record_tracker_state);
|
||||
auth_state = MLX5_GET(tls_progress_params, ctx, auth_state);
|
||||
if (tracker_state != MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING ||
|
||||
auth_state != MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD) {
|
||||
priv_rx->stats->tls_resync_req_skip++;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hw_seq = MLX5_GET(tls_progress_params, ctx, hw_resync_tcp_sn);
|
||||
tls_offload_rx_resync_async_request_end(priv_rx->sk, cpu_to_be32(hw_seq));
|
||||
priv_rx->stats->tls_resync_req_end++;
|
||||
out:
|
||||
refcount_dec(&resync->refcnt);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
/* Runs in NAPI.
|
||||
* Function elevates the refcount, unless no work is queued.
|
||||
*/
|
||||
static bool resync_queue_get_psv(struct sock *sk)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
struct mlx5e_ktls_rx_resync_ctx *resync;
|
||||
|
||||
priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_get_ctx(sk));
|
||||
if (unlikely(!priv_rx))
|
||||
return false;
|
||||
|
||||
if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags)))
|
||||
return false;
|
||||
|
||||
resync = &priv_rx->resync;
|
||||
refcount_inc(&resync->refcnt);
|
||||
if (unlikely(!queue_work(resync->priv->tls->rx_wq, &resync->work)))
|
||||
refcount_dec(&resync->refcnt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Runs in NAPI */
|
||||
static void resync_update_sn(struct mlx5e_rq *rq, struct sk_buff *skb)
|
||||
{
|
||||
struct ethhdr *eth = (struct ethhdr *)(skb->data);
|
||||
struct net_device *netdev = rq->netdev;
|
||||
struct sock *sk = NULL;
|
||||
unsigned int datalen;
|
||||
struct iphdr *iph;
|
||||
struct tcphdr *th;
|
||||
__be32 seq;
|
||||
int depth = 0;
|
||||
|
||||
__vlan_get_protocol(skb, eth->h_proto, &depth);
|
||||
iph = (struct iphdr *)(skb->data + depth);
|
||||
|
||||
if (iph->version == 4) {
|
||||
depth += sizeof(struct iphdr);
|
||||
th = (void *)iph + sizeof(struct iphdr);
|
||||
|
||||
sk = inet_lookup_established(dev_net(netdev), &tcp_hashinfo,
|
||||
iph->saddr, th->source, iph->daddr,
|
||||
th->dest, netdev->ifindex);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
} else {
|
||||
struct ipv6hdr *ipv6h = (struct ipv6hdr *)iph;
|
||||
|
||||
depth += sizeof(struct ipv6hdr);
|
||||
th = (void *)ipv6h + sizeof(struct ipv6hdr);
|
||||
|
||||
sk = __inet6_lookup_established(dev_net(netdev), &tcp_hashinfo,
|
||||
&ipv6h->saddr, th->source,
|
||||
&ipv6h->daddr, ntohs(th->dest),
|
||||
netdev->ifindex, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
depth += sizeof(struct tcphdr);
|
||||
|
||||
if (unlikely(!sk || sk->sk_state == TCP_TIME_WAIT))
|
||||
return;
|
||||
|
||||
if (unlikely(!resync_queue_get_psv(sk)))
|
||||
return;
|
||||
|
||||
skb->sk = sk;
|
||||
skb->destructor = sock_edemux;
|
||||
|
||||
seq = th->seq;
|
||||
datalen = skb->len - depth;
|
||||
tls_offload_rx_resync_async_request_start(sk, seq, datalen);
|
||||
rq->stats->tls_resync_req_start++;
|
||||
}
|
||||
|
||||
void mlx5e_ktls_rx_resync(struct net_device *netdev, struct sock *sk,
|
||||
u32 seq, u8 *rcd_sn)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
struct mlx5e_ktls_rx_resync_ctx *resync;
|
||||
struct mlx5e_priv *priv;
|
||||
struct mlx5e_channel *c;
|
||||
|
||||
priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_get_ctx(sk));
|
||||
if (unlikely(!priv_rx))
|
||||
return;
|
||||
|
||||
resync = &priv_rx->resync;
|
||||
resync->sw_rcd_sn_be = *(__be64 *)rcd_sn;
|
||||
resync->seq = seq;
|
||||
|
||||
priv = netdev_priv(netdev);
|
||||
c = priv->channels.c[priv_rx->rxq];
|
||||
|
||||
resync_handle_seq_match(priv_rx, c);
|
||||
}
|
||||
|
||||
/* End of resync section */
|
||||
|
||||
void mlx5e_ktls_handle_rx_skb(struct mlx5e_rq *rq, struct sk_buff *skb,
|
||||
struct mlx5_cqe64 *cqe, u32 *cqe_bcnt)
|
||||
{
|
||||
struct mlx5e_rq_stats *stats = rq->stats;
|
||||
|
||||
switch (get_cqe_tls_offload(cqe)) {
|
||||
case CQE_TLS_OFFLOAD_DECRYPTED:
|
||||
skb->decrypted = 1;
|
||||
stats->tls_decrypted_packets++;
|
||||
stats->tls_decrypted_bytes += *cqe_bcnt;
|
||||
break;
|
||||
case CQE_TLS_OFFLOAD_RESYNC:
|
||||
stats->tls_resync_req_pkt++;
|
||||
resync_update_sn(rq, skb);
|
||||
break;
|
||||
default: /* CQE_TLS_OFFLOAD_ERROR: */
|
||||
stats->tls_err++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mlx5e_ktls_handle_ctx_completion(struct mlx5e_icosq_wqe_info *wi)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx = wi->tls_set_params.priv_rx;
|
||||
struct accel_rule *rule = &priv_rx->rule;
|
||||
|
||||
if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) {
|
||||
complete(&priv_rx->add_ctx);
|
||||
return;
|
||||
}
|
||||
queue_work(rule->priv->tls->rx_wq, &rule->work);
|
||||
}
|
||||
|
||||
int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk,
|
||||
struct tls_crypto_info *crypto_info,
|
||||
u32 start_offload_tcp_sn)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
struct mlx5e_ktls_rx_resync_ctx *resync;
|
||||
struct tls_context *tls_ctx;
|
||||
struct mlx5_core_dev *mdev;
|
||||
struct mlx5e_priv *priv;
|
||||
int rxq, err;
|
||||
u32 rqtn;
|
||||
|
||||
tls_ctx = tls_get_ctx(sk);
|
||||
priv = netdev_priv(netdev);
|
||||
mdev = priv->mdev;
|
||||
priv_rx = kzalloc(sizeof(*priv_rx), GFP_KERNEL);
|
||||
if (unlikely(!priv_rx))
|
||||
return -ENOMEM;
|
||||
|
||||
err = mlx5_ktls_create_key(mdev, crypto_info, &priv_rx->key_id);
|
||||
if (err)
|
||||
goto err_create_key;
|
||||
|
||||
priv_rx->crypto_info =
|
||||
*(struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
|
||||
|
||||
rxq = mlx5e_accel_sk_get_rxq(sk);
|
||||
priv_rx->rxq = rxq;
|
||||
priv_rx->sk = sk;
|
||||
|
||||
priv_rx->stats = &priv->channel_stats[rxq].rq;
|
||||
mlx5e_set_ktls_rx_priv_ctx(tls_ctx, priv_rx);
|
||||
|
||||
rqtn = priv->direct_tir[rxq].rqt.rqtn;
|
||||
|
||||
err = mlx5e_ktls_create_tir(mdev, &priv_rx->tirn, rqtn);
|
||||
if (err)
|
||||
goto err_create_tir;
|
||||
|
||||
init_completion(&priv_rx->add_ctx);
|
||||
|
||||
accel_rule_init(&priv_rx->rule, priv, sk);
|
||||
resync = &priv_rx->resync;
|
||||
resync_init(resync, priv);
|
||||
tls_offload_ctx_rx(tls_ctx)->resync_async = &resync->core;
|
||||
tls_offload_rx_resync_set_type(sk, TLS_OFFLOAD_SYNC_TYPE_DRIVER_REQ_ASYNC);
|
||||
|
||||
err = post_rx_param_wqes(priv->channels.c[rxq], priv_rx, start_offload_tcp_sn);
|
||||
if (err)
|
||||
goto err_post_wqes;
|
||||
|
||||
priv_rx->stats->tls_ctx++;
|
||||
|
||||
return 0;
|
||||
|
||||
err_post_wqes:
|
||||
mlx5_core_destroy_tir(mdev, priv_rx->tirn);
|
||||
err_create_tir:
|
||||
mlx5_ktls_destroy_key(mdev, priv_rx->key_id);
|
||||
err_create_key:
|
||||
kfree(priv_rx);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Elevated refcount on the resync object means there are
|
||||
* outstanding operations (uncompleted GET_PSV WQEs) that
|
||||
* will read the resync / priv_rx objects once completed.
|
||||
* Wait for them to avoid use-after-free.
|
||||
*/
|
||||
static void wait_for_resync(struct net_device *netdev,
|
||||
struct mlx5e_ktls_rx_resync_ctx *resync)
|
||||
{
|
||||
#define MLX5E_KTLS_RX_RESYNC_TIMEOUT 20000 /* msecs */
|
||||
unsigned long exp_time = jiffies + msecs_to_jiffies(MLX5E_KTLS_RX_RESYNC_TIMEOUT);
|
||||
unsigned int refcnt;
|
||||
|
||||
do {
|
||||
refcnt = refcount_read(&resync->refcnt);
|
||||
if (refcnt == 1)
|
||||
return;
|
||||
|
||||
msleep(20);
|
||||
} while (time_before(jiffies, exp_time));
|
||||
|
||||
netdev_warn(netdev,
|
||||
"Failed waiting for kTLS RX resync refcnt to be released (%u).\n",
|
||||
refcnt);
|
||||
}
|
||||
|
||||
void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx)
|
||||
{
|
||||
struct mlx5e_ktls_offload_context_rx *priv_rx;
|
||||
struct mlx5e_ktls_rx_resync_ctx *resync;
|
||||
struct mlx5_core_dev *mdev;
|
||||
struct mlx5e_priv *priv;
|
||||
|
||||
priv = netdev_priv(netdev);
|
||||
mdev = priv->mdev;
|
||||
|
||||
priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_ctx);
|
||||
set_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags);
|
||||
mlx5e_set_ktls_rx_priv_ctx(tls_ctx, NULL);
|
||||
napi_synchronize(&priv->channels.c[priv_rx->rxq]->napi);
|
||||
if (!cancel_work_sync(&priv_rx->rule.work))
|
||||
/* completion is needed, as the priv_rx in the add flow
|
||||
* is maintained on the wqe info (wi), not on the socket.
|
||||
*/
|
||||
wait_for_completion(&priv_rx->add_ctx);
|
||||
resync = &priv_rx->resync;
|
||||
if (cancel_work_sync(&resync->work))
|
||||
refcount_dec(&resync->refcnt);
|
||||
wait_for_resync(netdev, resync);
|
||||
|
||||
priv_rx->stats->tls_del++;
|
||||
if (priv_rx->rule.rule)
|
||||
mlx5e_accel_fs_del_sk(priv_rx->rule.rule);
|
||||
|
||||
mlx5_core_destroy_tir(mdev, priv_rx->tirn);
|
||||
mlx5_ktls_destroy_key(mdev, priv_rx->key_id);
|
||||
kfree(priv_rx);
|
||||
}
|
@ -1,105 +1,139 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
// Copyright (c) 2019 Mellanox Technologies.
|
||||
|
||||
#include <linux/tls.h>
|
||||
#include "en.h"
|
||||
#include "en/txrx.h"
|
||||
#include "en_accel/ktls.h"
|
||||
#include "en_accel/ktls_txrx.h"
|
||||
#include "en_accel/ktls_utils.h"
|
||||
|
||||
enum {
|
||||
MLX5E_STATIC_PARAMS_CONTEXT_TLS_1_2 = 0x2,
|
||||
struct mlx5e_dump_wqe {
|
||||
struct mlx5_wqe_ctrl_seg ctrl;
|
||||
struct mlx5_wqe_data_seg data;
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5E_ENCRYPTION_STANDARD_TLS = 0x1,
|
||||
#define MLX5E_KTLS_DUMP_WQEBBS \
|
||||
(DIV_ROUND_UP(sizeof(struct mlx5e_dump_wqe), MLX5_SEND_WQE_BB))
|
||||
|
||||
static u8
|
||||
mlx5e_ktls_dumps_num_wqes(struct mlx5e_txqsq *sq, unsigned int nfrags,
|
||||
unsigned int sync_len)
|
||||
{
|
||||
/* Given the MTU and sync_len, calculates an upper bound for the
|
||||
* number of DUMP WQEs needed for the TX resync of a record.
|
||||
*/
|
||||
return nfrags + DIV_ROUND_UP(sync_len, sq->hw_mtu);
|
||||
}
|
||||
|
||||
u16 mlx5e_ktls_get_stop_room(struct mlx5e_txqsq *sq)
|
||||
{
|
||||
u16 num_dumps, stop_room = 0;
|
||||
|
||||
num_dumps = mlx5e_ktls_dumps_num_wqes(sq, MAX_SKB_FRAGS, TLS_MAX_PAYLOAD_SIZE);
|
||||
|
||||
stop_room += mlx5e_stop_room_for_wqe(MLX5E_TLS_SET_STATIC_PARAMS_WQEBBS);
|
||||
stop_room += mlx5e_stop_room_for_wqe(MLX5E_TLS_SET_PROGRESS_PARAMS_WQEBBS);
|
||||
stop_room += num_dumps * mlx5e_stop_room_for_wqe(MLX5E_KTLS_DUMP_WQEBBS);
|
||||
|
||||
return stop_room;
|
||||
}
|
||||
|
||||
static int mlx5e_ktls_create_tis(struct mlx5_core_dev *mdev, u32 *tisn)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {};
|
||||
void *tisc;
|
||||
|
||||
tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
|
||||
|
||||
MLX5_SET(tisc, tisc, tls_en, 1);
|
||||
|
||||
return mlx5e_create_tis(mdev, in, tisn);
|
||||
}
|
||||
|
||||
struct mlx5e_ktls_offload_context_tx {
|
||||
struct tls_offload_context_tx *tx_ctx;
|
||||
struct tls12_crypto_info_aes_gcm_128 crypto_info;
|
||||
u32 expected_seq;
|
||||
u32 tisn;
|
||||
u32 key_id;
|
||||
bool ctx_post_pending;
|
||||
};
|
||||
|
||||
#define EXTRACT_INFO_FIELDS do { \
|
||||
salt = info->salt; \
|
||||
rec_seq = info->rec_seq; \
|
||||
salt_sz = sizeof(info->salt); \
|
||||
rec_seq_sz = sizeof(info->rec_seq); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
fill_static_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx)
|
||||
mlx5e_set_ktls_tx_priv_ctx(struct tls_context *tls_ctx,
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx)
|
||||
{
|
||||
struct tls12_crypto_info_aes_gcm_128 *info = &priv_tx->crypto_info;
|
||||
char *initial_rn, *gcm_iv;
|
||||
u16 salt_sz, rec_seq_sz;
|
||||
char *salt, *rec_seq;
|
||||
u8 tls_version;
|
||||
struct mlx5e_ktls_offload_context_tx **ctx =
|
||||
__tls_driver_ctx(tls_ctx, TLS_OFFLOAD_CTX_DIR_TX);
|
||||
|
||||
EXTRACT_INFO_FIELDS;
|
||||
BUILD_BUG_ON(sizeof(struct mlx5e_ktls_offload_context_tx *) >
|
||||
TLS_OFFLOAD_CONTEXT_SIZE_TX);
|
||||
|
||||
gcm_iv = MLX5_ADDR_OF(tls_static_params, ctx, gcm_iv);
|
||||
initial_rn = MLX5_ADDR_OF(tls_static_params, ctx, initial_record_number);
|
||||
|
||||
memcpy(gcm_iv, salt, salt_sz);
|
||||
memcpy(initial_rn, rec_seq, rec_seq_sz);
|
||||
|
||||
tls_version = MLX5E_STATIC_PARAMS_CONTEXT_TLS_1_2;
|
||||
|
||||
MLX5_SET(tls_static_params, ctx, tls_version, tls_version);
|
||||
MLX5_SET(tls_static_params, ctx, const_1, 1);
|
||||
MLX5_SET(tls_static_params, ctx, const_2, 2);
|
||||
MLX5_SET(tls_static_params, ctx, encryption_standard,
|
||||
MLX5E_ENCRYPTION_STANDARD_TLS);
|
||||
MLX5_SET(tls_static_params, ctx, dek_index, priv_tx->key_id);
|
||||
*ctx = priv_tx;
|
||||
}
|
||||
|
||||
static void
|
||||
build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx,
|
||||
bool fence)
|
||||
static struct mlx5e_ktls_offload_context_tx *
|
||||
mlx5e_get_ktls_tx_priv_ctx(struct tls_context *tls_ctx)
|
||||
{
|
||||
struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl;
|
||||
struct mlx5_wqe_umr_ctrl_seg *ucseg = &wqe->uctrl;
|
||||
struct mlx5e_ktls_offload_context_tx **ctx =
|
||||
__tls_driver_ctx(tls_ctx, TLS_OFFLOAD_CTX_DIR_TX);
|
||||
|
||||
#define STATIC_PARAMS_DS_CNT \
|
||||
DIV_ROUND_UP(MLX5E_KTLS_STATIC_UMR_WQE_SZ, MLX5_SEND_WQE_DS)
|
||||
|
||||
cseg->opmod_idx_opcode = cpu_to_be32((pc << 8) | MLX5_OPCODE_UMR |
|
||||
(MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS << 24));
|
||||
cseg->qpn_ds = cpu_to_be32((sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
|
||||
STATIC_PARAMS_DS_CNT);
|
||||
cseg->fm_ce_se = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
|
||||
cseg->tisn = cpu_to_be32(priv_tx->tisn << 8);
|
||||
|
||||
ucseg->flags = MLX5_UMR_INLINE;
|
||||
ucseg->bsf_octowords = cpu_to_be16(MLX5_ST_SZ_BYTES(tls_static_params) / 16);
|
||||
|
||||
fill_static_params_ctx(wqe->tls_static_params_ctx, priv_tx);
|
||||
return *ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_progress_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx)
|
||||
int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk,
|
||||
struct tls_crypto_info *crypto_info, u32 start_offload_tcp_sn)
|
||||
{
|
||||
MLX5_SET(tls_progress_params, ctx, tisn, priv_tx->tisn);
|
||||
MLX5_SET(tls_progress_params, ctx, record_tracker_state,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START);
|
||||
MLX5_SET(tls_progress_params, ctx, auth_state,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD);
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx;
|
||||
struct tls_context *tls_ctx;
|
||||
struct mlx5_core_dev *mdev;
|
||||
struct mlx5e_priv *priv;
|
||||
int err;
|
||||
|
||||
tls_ctx = tls_get_ctx(sk);
|
||||
priv = netdev_priv(netdev);
|
||||
mdev = priv->mdev;
|
||||
|
||||
priv_tx = kzalloc(sizeof(*priv_tx), GFP_KERNEL);
|
||||
if (!priv_tx)
|
||||
return -ENOMEM;
|
||||
|
||||
err = mlx5_ktls_create_key(mdev, crypto_info, &priv_tx->key_id);
|
||||
if (err)
|
||||
goto err_create_key;
|
||||
|
||||
priv_tx->expected_seq = start_offload_tcp_sn;
|
||||
priv_tx->crypto_info =
|
||||
*(struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
|
||||
priv_tx->tx_ctx = tls_offload_ctx_tx(tls_ctx);
|
||||
|
||||
mlx5e_set_ktls_tx_priv_ctx(tls_ctx, priv_tx);
|
||||
|
||||
err = mlx5e_ktls_create_tis(mdev, &priv_tx->tisn);
|
||||
if (err)
|
||||
goto err_create_tis;
|
||||
|
||||
priv_tx->ctx_post_pending = true;
|
||||
|
||||
return 0;
|
||||
|
||||
err_create_tis:
|
||||
mlx5_ktls_destroy_key(mdev, priv_tx->key_id);
|
||||
err_create_key:
|
||||
kfree(priv_tx);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
build_progress_params(struct mlx5e_tx_wqe *wqe, u16 pc, u32 sqn,
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx,
|
||||
bool fence)
|
||||
void mlx5e_ktls_del_tx(struct net_device *netdev, struct tls_context *tls_ctx)
|
||||
{
|
||||
struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl;
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx;
|
||||
struct mlx5_core_dev *mdev;
|
||||
struct mlx5e_priv *priv;
|
||||
|
||||
#define PROGRESS_PARAMS_DS_CNT \
|
||||
DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_DS)
|
||||
priv_tx = mlx5e_get_ktls_tx_priv_ctx(tls_ctx);
|
||||
priv = netdev_priv(netdev);
|
||||
mdev = priv->mdev;
|
||||
|
||||
cseg->opmod_idx_opcode =
|
||||
cpu_to_be32((pc << 8) | MLX5_OPCODE_SET_PSV |
|
||||
(MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS << 24));
|
||||
cseg->qpn_ds = cpu_to_be32((sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
|
||||
PROGRESS_PARAMS_DS_CNT);
|
||||
cseg->fm_ce_se = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
|
||||
|
||||
fill_progress_params_ctx(wqe->tls_progress_params_ctx, priv_tx);
|
||||
mlx5e_destroy_tis(mdev, priv_tx->tisn);
|
||||
mlx5_ktls_destroy_key(mdev, priv_tx->key_id);
|
||||
kfree(priv_tx);
|
||||
}
|
||||
|
||||
static void tx_fill_wi(struct mlx5e_txqsq *sq,
|
||||
@ -115,11 +149,6 @@ static void tx_fill_wi(struct mlx5e_txqsq *sq,
|
||||
};
|
||||
}
|
||||
|
||||
void mlx5e_ktls_tx_offload_set_pending(struct mlx5e_ktls_offload_context_tx *priv_tx)
|
||||
{
|
||||
priv_tx->ctx_post_pending = true;
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_ktls_tx_offload_test_and_clear_pending(struct mlx5e_ktls_offload_context_tx *priv_tx)
|
||||
{
|
||||
@ -135,12 +164,15 @@ post_static_params(struct mlx5e_txqsq *sq,
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx,
|
||||
bool fence)
|
||||
{
|
||||
u16 pi, num_wqebbs = MLX5E_KTLS_STATIC_WQEBBS;
|
||||
struct mlx5e_umr_wqe *umr_wqe;
|
||||
struct mlx5e_set_tls_static_params_wqe *wqe;
|
||||
u16 pi, num_wqebbs;
|
||||
|
||||
num_wqebbs = MLX5E_TLS_SET_STATIC_PARAMS_WQEBBS;
|
||||
pi = mlx5e_txqsq_get_next_pi(sq, num_wqebbs);
|
||||
umr_wqe = MLX5E_TLS_FETCH_UMR_WQE(sq, pi);
|
||||
build_static_params(umr_wqe, sq->pc, sq->sqn, priv_tx, fence);
|
||||
wqe = MLX5E_TLS_FETCH_SET_STATIC_PARAMS_WQE(sq, pi);
|
||||
mlx5e_ktls_build_static_params(wqe, sq->pc, sq->sqn, &priv_tx->crypto_info,
|
||||
priv_tx->tisn, priv_tx->key_id, 0, fence,
|
||||
TLS_OFFLOAD_CTX_DIR_TX);
|
||||
tx_fill_wi(sq, pi, num_wqebbs, 0, NULL);
|
||||
sq->pc += num_wqebbs;
|
||||
}
|
||||
@ -150,12 +182,14 @@ post_progress_params(struct mlx5e_txqsq *sq,
|
||||
struct mlx5e_ktls_offload_context_tx *priv_tx,
|
||||
bool fence)
|
||||
{
|
||||
u16 pi, num_wqebbs = MLX5E_KTLS_PROGRESS_WQEBBS;
|
||||
struct mlx5e_tx_wqe *wqe;
|
||||
struct mlx5e_set_tls_progress_params_wqe *wqe;
|
||||
u16 pi, num_wqebbs;
|
||||
|
||||
num_wqebbs = MLX5E_TLS_SET_PROGRESS_PARAMS_WQEBBS;
|
||||
pi = mlx5e_txqsq_get_next_pi(sq, num_wqebbs);
|
||||
wqe = MLX5E_TLS_FETCH_PROGRESS_WQE(sq, pi);
|
||||
build_progress_params(wqe, sq->pc, sq->sqn, priv_tx, fence);
|
||||
wqe = MLX5E_TLS_FETCH_SET_PROGRESS_PARAMS_WQE(sq, pi);
|
||||
mlx5e_ktls_build_progress_params(wqe, sq->pc, sq->sqn, priv_tx->tisn, fence, 0,
|
||||
TLS_OFFLOAD_CTX_DIR_TX);
|
||||
tx_fill_wi(sq, pi, num_wqebbs, 0, NULL);
|
||||
sq->pc += num_wqebbs;
|
||||
}
|
||||
@ -284,7 +318,7 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool fir
|
||||
|
||||
cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | MLX5_OPCODE_DUMP);
|
||||
cseg->qpn_ds = cpu_to_be32((sq->sqn << 8) | ds_cnt);
|
||||
cseg->tisn = cpu_to_be32(tisn << 8);
|
||||
cseg->tis_tir_num = cpu_to_be32(tisn << 8);
|
||||
cseg->fm_ce_se = first ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
|
||||
|
||||
fsz = skb_frag_size(frag);
|
||||
|
119
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.c
Normal file
119
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.c
Normal file
@ -0,0 +1,119 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */
|
||||
|
||||
#include "en_accel/ktls_txrx.h"
|
||||
#include "en_accel/ktls_utils.h"
|
||||
|
||||
enum {
|
||||
MLX5E_STATIC_PARAMS_CONTEXT_TLS_1_2 = 0x2,
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5E_ENCRYPTION_STANDARD_TLS = 0x1,
|
||||
};
|
||||
|
||||
#define EXTRACT_INFO_FIELDS do { \
|
||||
salt = info->salt; \
|
||||
rec_seq = info->rec_seq; \
|
||||
salt_sz = sizeof(info->salt); \
|
||||
rec_seq_sz = sizeof(info->rec_seq); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
fill_static_params(struct mlx5_wqe_tls_static_params_seg *params,
|
||||
struct tls12_crypto_info_aes_gcm_128 *info,
|
||||
u32 key_id, u32 resync_tcp_sn)
|
||||
{
|
||||
char *initial_rn, *gcm_iv;
|
||||
u16 salt_sz, rec_seq_sz;
|
||||
char *salt, *rec_seq;
|
||||
u8 tls_version;
|
||||
u8 *ctx;
|
||||
|
||||
ctx = params->ctx;
|
||||
|
||||
EXTRACT_INFO_FIELDS;
|
||||
|
||||
gcm_iv = MLX5_ADDR_OF(tls_static_params, ctx, gcm_iv);
|
||||
initial_rn = MLX5_ADDR_OF(tls_static_params, ctx, initial_record_number);
|
||||
|
||||
memcpy(gcm_iv, salt, salt_sz);
|
||||
memcpy(initial_rn, rec_seq, rec_seq_sz);
|
||||
|
||||
tls_version = MLX5E_STATIC_PARAMS_CONTEXT_TLS_1_2;
|
||||
|
||||
MLX5_SET(tls_static_params, ctx, tls_version, tls_version);
|
||||
MLX5_SET(tls_static_params, ctx, const_1, 1);
|
||||
MLX5_SET(tls_static_params, ctx, const_2, 2);
|
||||
MLX5_SET(tls_static_params, ctx, encryption_standard,
|
||||
MLX5E_ENCRYPTION_STANDARD_TLS);
|
||||
MLX5_SET(tls_static_params, ctx, resync_tcp_sn, resync_tcp_sn);
|
||||
MLX5_SET(tls_static_params, ctx, dek_index, key_id);
|
||||
}
|
||||
|
||||
void
|
||||
mlx5e_ktls_build_static_params(struct mlx5e_set_tls_static_params_wqe *wqe,
|
||||
u16 pc, u32 sqn,
|
||||
struct tls12_crypto_info_aes_gcm_128 *info,
|
||||
u32 tis_tir_num, u32 key_id, u32 resync_tcp_sn,
|
||||
bool fence, enum tls_offload_ctx_dir direction)
|
||||
{
|
||||
struct mlx5_wqe_umr_ctrl_seg *ucseg = &wqe->uctrl;
|
||||
struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl;
|
||||
u8 opmod = direction == TLS_OFFLOAD_CTX_DIR_TX ?
|
||||
MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS :
|
||||
MLX5_OPC_MOD_TLS_TIR_STATIC_PARAMS;
|
||||
|
||||
#define STATIC_PARAMS_DS_CNT DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS)
|
||||
|
||||
cseg->opmod_idx_opcode = cpu_to_be32((pc << 8) | MLX5_OPCODE_UMR | (opmod << 24));
|
||||
cseg->qpn_ds = cpu_to_be32((sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
|
||||
STATIC_PARAMS_DS_CNT);
|
||||
cseg->fm_ce_se = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
|
||||
cseg->tis_tir_num = cpu_to_be32(tis_tir_num << 8);
|
||||
|
||||
ucseg->flags = MLX5_UMR_INLINE;
|
||||
ucseg->bsf_octowords = cpu_to_be16(MLX5_ST_SZ_BYTES(tls_static_params) / 16);
|
||||
|
||||
fill_static_params(&wqe->params, info, key_id, resync_tcp_sn);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_progress_params(struct mlx5_wqe_tls_progress_params_seg *params, u32 tis_tir_num,
|
||||
u32 next_record_tcp_sn)
|
||||
{
|
||||
u8 *ctx = params->ctx;
|
||||
|
||||
params->tis_tir_num = cpu_to_be32(tis_tir_num);
|
||||
|
||||
MLX5_SET(tls_progress_params, ctx, next_record_tcp_sn,
|
||||
next_record_tcp_sn);
|
||||
MLX5_SET(tls_progress_params, ctx, record_tracker_state,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START);
|
||||
MLX5_SET(tls_progress_params, ctx, auth_state,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD);
|
||||
}
|
||||
|
||||
void
|
||||
mlx5e_ktls_build_progress_params(struct mlx5e_set_tls_progress_params_wqe *wqe,
|
||||
u16 pc, u32 sqn,
|
||||
u32 tis_tir_num, bool fence,
|
||||
u32 next_record_tcp_sn,
|
||||
enum tls_offload_ctx_dir direction)
|
||||
{
|
||||
struct mlx5_wqe_ctrl_seg *cseg = &wqe->ctrl;
|
||||
u8 opmod = direction == TLS_OFFLOAD_CTX_DIR_TX ?
|
||||
MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS :
|
||||
MLX5_OPC_MOD_TLS_TIR_PROGRESS_PARAMS;
|
||||
|
||||
#define PROGRESS_PARAMS_DS_CNT DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS)
|
||||
|
||||
cseg->opmod_idx_opcode =
|
||||
cpu_to_be32((pc << 8) | MLX5_OPCODE_SET_PSV | (opmod << 24));
|
||||
cseg->qpn_ds = cpu_to_be32((sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
|
||||
PROGRESS_PARAMS_DS_CNT);
|
||||
cseg->fm_ce_se = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
|
||||
|
||||
fill_progress_params(&wqe->params, tis_tir_num, next_record_tcp_sn);
|
||||
}
|
||||
|
42
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h
Normal file
42
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */
|
||||
|
||||
#ifndef __MLX5E_KTLS_TXRX_H__
|
||||
#define __MLX5E_KTLS_TXRX_H__
|
||||
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
|
||||
#include <net/tls.h>
|
||||
#include "en.h"
|
||||
#include "en/txrx.h"
|
||||
|
||||
struct mlx5e_accel_tx_tls_state {
|
||||
u32 tls_tisn;
|
||||
};
|
||||
|
||||
u16 mlx5e_ktls_get_stop_room(struct mlx5e_txqsq *sq);
|
||||
|
||||
bool mlx5e_ktls_handle_tx_skb(struct tls_context *tls_ctx, struct mlx5e_txqsq *sq,
|
||||
struct sk_buff *skb, int datalen,
|
||||
struct mlx5e_accel_tx_tls_state *state);
|
||||
void mlx5e_ktls_handle_rx_skb(struct mlx5e_rq *rq, struct sk_buff *skb,
|
||||
struct mlx5_cqe64 *cqe, u32 *cqe_bcnt);
|
||||
|
||||
void mlx5e_ktls_handle_ctx_completion(struct mlx5e_icosq_wqe_info *wi);
|
||||
void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
|
||||
struct mlx5e_icosq *sq);
|
||||
|
||||
void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
|
||||
struct mlx5e_tx_wqe_info *wi,
|
||||
u32 *dma_fifo_cc);
|
||||
#else
|
||||
static inline void
|
||||
mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
|
||||
struct mlx5e_tx_wqe_info *wi,
|
||||
u32 *dma_fifo_cc)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MLX5_EN_TLS */
|
||||
|
||||
#endif /* __MLX5E_TLS_TXRX_H__ */
|
@ -0,0 +1,86 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */
|
||||
|
||||
#ifndef __MLX5E_KTLS_UTILS_H__
|
||||
#define __MLX5E_KTLS_UTILS_H__
|
||||
|
||||
#include <net/tls.h>
|
||||
#include "en.h"
|
||||
#include "accel/tls.h"
|
||||
|
||||
enum {
|
||||
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD = 0,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_OFFLOAD = 1,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_AUTHENTICATION = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START = 0,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING = 1,
|
||||
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING = 2,
|
||||
};
|
||||
|
||||
int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk,
|
||||
struct tls_crypto_info *crypto_info, u32 start_offload_tcp_sn);
|
||||
void mlx5e_ktls_del_tx(struct net_device *netdev, struct tls_context *tls_ctx);
|
||||
int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk,
|
||||
struct tls_crypto_info *crypto_info, u32 start_offload_tcp_sn);
|
||||
void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx);
|
||||
void mlx5e_ktls_rx_resync(struct net_device *netdev, struct sock *sk, u32 seq, u8 *rcd_sn);
|
||||
|
||||
struct mlx5e_set_tls_static_params_wqe {
|
||||
struct mlx5_wqe_ctrl_seg ctrl;
|
||||
struct mlx5_wqe_umr_ctrl_seg uctrl;
|
||||
struct mlx5_mkey_seg mkc;
|
||||
struct mlx5_wqe_tls_static_params_seg params;
|
||||
};
|
||||
|
||||
struct mlx5e_set_tls_progress_params_wqe {
|
||||
struct mlx5_wqe_ctrl_seg ctrl;
|
||||
struct mlx5_wqe_tls_progress_params_seg params;
|
||||
};
|
||||
|
||||
struct mlx5e_get_tls_progress_params_wqe {
|
||||
struct mlx5_wqe_ctrl_seg ctrl;
|
||||
struct mlx5_seg_get_psv psv;
|
||||
};
|
||||
|
||||
#define MLX5E_TLS_SET_STATIC_PARAMS_WQEBBS \
|
||||
(DIV_ROUND_UP(sizeof(struct mlx5e_set_tls_static_params_wqe), MLX5_SEND_WQE_BB))
|
||||
|
||||
#define MLX5E_TLS_SET_PROGRESS_PARAMS_WQEBBS \
|
||||
(DIV_ROUND_UP(sizeof(struct mlx5e_set_tls_progress_params_wqe), MLX5_SEND_WQE_BB))
|
||||
|
||||
#define MLX5E_KTLS_GET_PROGRESS_WQEBBS \
|
||||
(DIV_ROUND_UP(sizeof(struct mlx5e_get_tls_progress_params_wqe), MLX5_SEND_WQE_BB))
|
||||
|
||||
#define MLX5E_TLS_FETCH_SET_STATIC_PARAMS_WQE(sq, pi) \
|
||||
((struct mlx5e_set_tls_static_params_wqe *)\
|
||||
mlx5e_fetch_wqe(&(sq)->wq, pi, sizeof(struct mlx5e_set_tls_static_params_wqe)))
|
||||
|
||||
#define MLX5E_TLS_FETCH_SET_PROGRESS_PARAMS_WQE(sq, pi) \
|
||||
((struct mlx5e_set_tls_progress_params_wqe *)\
|
||||
mlx5e_fetch_wqe(&(sq)->wq, pi, sizeof(struct mlx5e_set_tls_progress_params_wqe)))
|
||||
|
||||
#define MLX5E_TLS_FETCH_GET_PROGRESS_PARAMS_WQE(sq, pi) \
|
||||
((struct mlx5e_get_tls_progress_params_wqe *)\
|
||||
mlx5e_fetch_wqe(&(sq)->wq, pi, sizeof(struct mlx5e_get_tls_progress_params_wqe)))
|
||||
|
||||
#define MLX5E_TLS_FETCH_DUMP_WQE(sq, pi) \
|
||||
((struct mlx5e_dump_wqe *)\
|
||||
mlx5e_fetch_wqe(&(sq)->wq, pi, sizeof(struct mlx5e_dump_wqe)))
|
||||
|
||||
void
|
||||
mlx5e_ktls_build_static_params(struct mlx5e_set_tls_static_params_wqe *wqe,
|
||||
u16 pc, u32 sqn,
|
||||
struct tls12_crypto_info_aes_gcm_128 *info,
|
||||
u32 tis_tir_num, u32 key_id, u32 resync_tcp_sn,
|
||||
bool fence, enum tls_offload_ctx_dir direction);
|
||||
void
|
||||
mlx5e_ktls_build_progress_params(struct mlx5e_set_tls_progress_params_wqe *wqe,
|
||||
u16 pc, u32 sqn,
|
||||
u32 tis_tir_num, bool fence,
|
||||
u32 next_record_tcp_sn,
|
||||
enum tls_offload_ctx_dir direction);
|
||||
|
||||
#endif /* __MLX5E_TLS_UTILS_H__ */
|
@ -197,6 +197,7 @@ void mlx5e_tls_build_netdev(struct mlx5e_priv *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
/* FPGA */
|
||||
if (!mlx5_accel_is_tls_device(priv->mdev))
|
||||
return;
|
||||
|
||||
@ -221,11 +222,19 @@ void mlx5e_tls_build_netdev(struct mlx5e_priv *priv)
|
||||
|
||||
int mlx5e_tls_init(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_tls *tls = kzalloc(sizeof(*tls), GFP_KERNEL);
|
||||
struct mlx5e_tls *tls;
|
||||
|
||||
if (!mlx5_accel_is_tls_device(priv->mdev))
|
||||
return 0;
|
||||
|
||||
tls = kzalloc(sizeof(*tls), GFP_KERNEL);
|
||||
if (!tls)
|
||||
return -ENOMEM;
|
||||
|
||||
tls->rx_wq = create_singlethread_workqueue("mlx5e_tls_rx");
|
||||
if (!tls->rx_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->tls = tls;
|
||||
return 0;
|
||||
}
|
||||
@ -237,20 +246,7 @@ void mlx5e_tls_cleanup(struct mlx5e_priv *priv)
|
||||
if (!tls)
|
||||
return;
|
||||
|
||||
destroy_workqueue(tls->rx_wq);
|
||||
kfree(tls);
|
||||
priv->tls = NULL;
|
||||
}
|
||||
|
||||
u16 mlx5e_tls_get_stop_room(struct mlx5e_txqsq *sq)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = sq->channel->mdev;
|
||||
|
||||
if (!mlx5_accel_is_tls_device(mdev))
|
||||
return 0;
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, tls_tx))
|
||||
return mlx5e_ktls_get_stop_room(sq);
|
||||
|
||||
/* Resync SKB. */
|
||||
return mlx5e_stop_room_for_wqe(MLX5_SEND_WQE_MAX_WQEBBS);
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ struct mlx5e_tls_sw_stats {
|
||||
|
||||
struct mlx5e_tls {
|
||||
struct mlx5e_tls_sw_stats sw_stats;
|
||||
struct workqueue_struct *rx_wq;
|
||||
};
|
||||
|
||||
struct mlx5e_tls_offload_context_tx {
|
||||
@ -86,6 +87,11 @@ mlx5e_get_tls_rx_context(struct tls_context *tls_ctx)
|
||||
base);
|
||||
}
|
||||
|
||||
static inline bool mlx5e_is_tls_on(struct mlx5e_priv *priv)
|
||||
{
|
||||
return priv->tls;
|
||||
}
|
||||
|
||||
void mlx5e_tls_build_netdev(struct mlx5e_priv *priv);
|
||||
int mlx5e_tls_init(struct mlx5e_priv *priv);
|
||||
void mlx5e_tls_cleanup(struct mlx5e_priv *priv);
|
||||
@ -94,8 +100,6 @@ int mlx5e_tls_get_count(struct mlx5e_priv *priv);
|
||||
int mlx5e_tls_get_strings(struct mlx5e_priv *priv, uint8_t *data);
|
||||
int mlx5e_tls_get_stats(struct mlx5e_priv *priv, u64 *data);
|
||||
|
||||
u16 mlx5e_tls_get_stop_room(struct mlx5e_txqsq *sq);
|
||||
|
||||
#else
|
||||
|
||||
static inline void mlx5e_tls_build_netdev(struct mlx5e_priv *priv)
|
||||
@ -104,17 +108,13 @@ static inline void mlx5e_tls_build_netdev(struct mlx5e_priv *priv)
|
||||
mlx5e_ktls_build_netdev(priv);
|
||||
}
|
||||
|
||||
static inline bool mlx5e_is_tls_on(struct mlx5e_priv *priv) { return false; }
|
||||
static inline int mlx5e_tls_init(struct mlx5e_priv *priv) { return 0; }
|
||||
static inline void mlx5e_tls_cleanup(struct mlx5e_priv *priv) { }
|
||||
static inline int mlx5e_tls_get_count(struct mlx5e_priv *priv) { return 0; }
|
||||
static inline int mlx5e_tls_get_strings(struct mlx5e_priv *priv, uint8_t *data) { return 0; }
|
||||
static inline int mlx5e_tls_get_stats(struct mlx5e_priv *priv, u64 *data) { return 0; }
|
||||
|
||||
static inline u16 mlx5e_tls_get_stop_room(struct mlx5e_txqsq *sq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __MLX5E_TLS_H__ */
|
||||
|
@ -278,9 +278,10 @@ bool mlx5e_tls_handle_tx_skb(struct net_device *netdev, struct mlx5e_txqsq *sq,
|
||||
if (WARN_ON_ONCE(tls_ctx->netdev != netdev))
|
||||
goto err_out;
|
||||
|
||||
if (MLX5_CAP_GEN(sq->channel->mdev, tls_tx))
|
||||
if (mlx5_accel_is_ktls_tx(sq->channel->mdev))
|
||||
return mlx5e_ktls_handle_tx_skb(tls_ctx, sq, skb, datalen, state);
|
||||
|
||||
/* FPGA */
|
||||
skb_seq = ntohl(tcp_hdr(skb)->seq);
|
||||
context = mlx5e_get_tls_tx_context(tls_ctx);
|
||||
expected_seq = context->expected_seq;
|
||||
@ -305,7 +306,7 @@ err_out:
|
||||
void mlx5e_tls_handle_tx_wqe(struct mlx5e_txqsq *sq, struct mlx5_wqe_ctrl_seg *cseg,
|
||||
struct mlx5e_accel_tx_tls_state *state)
|
||||
{
|
||||
cseg->tisn = cpu_to_be32(state->tls_tisn << 8);
|
||||
cseg->tis_tir_num = cpu_to_be32(state->tls_tisn << 8);
|
||||
}
|
||||
|
||||
static int tls_update_resync_sn(struct net_device *netdev,
|
||||
@ -354,15 +355,13 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
|
||||
u32 *cqe_bcnt)
|
||||
/* FPGA tls rx handler */
|
||||
void mlx5e_tls_handle_rx_skb_metadata(struct mlx5e_rq *rq, struct sk_buff *skb,
|
||||
u32 *cqe_bcnt)
|
||||
{
|
||||
struct mlx5e_tls_metadata *mdata;
|
||||
struct mlx5e_priv *priv;
|
||||
|
||||
if (!is_metadata_hdr_valid(skb))
|
||||
return;
|
||||
|
||||
/* Use the metadata */
|
||||
mdata = (struct mlx5e_tls_metadata *)(skb->data + ETH_HLEN);
|
||||
switch (mdata->content.recv.syndrome) {
|
||||
@ -370,13 +369,13 @@ void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
|
||||
skb->decrypted = 1;
|
||||
break;
|
||||
case SYNDROM_RESYNC_REQUEST:
|
||||
tls_update_resync_sn(netdev, skb, mdata);
|
||||
priv = netdev_priv(netdev);
|
||||
tls_update_resync_sn(rq->netdev, skb, mdata);
|
||||
priv = netdev_priv(rq->netdev);
|
||||
atomic64_inc(&priv->tls->sw_stats.rx_tls_resync_request);
|
||||
break;
|
||||
case SYNDROM_AUTH_FAILED:
|
||||
/* Authentication failure will be observed and verified by kTLS */
|
||||
priv = netdev_priv(netdev);
|
||||
priv = netdev_priv(rq->netdev);
|
||||
atomic64_inc(&priv->tls->sw_stats.rx_tls_auth_fail);
|
||||
break;
|
||||
default:
|
||||
@ -387,3 +386,18 @@ void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
|
||||
remove_metadata_hdr(skb);
|
||||
*cqe_bcnt -= MLX5E_METADATA_ETHER_LEN;
|
||||
}
|
||||
|
||||
u16 mlx5e_tls_get_stop_room(struct mlx5e_txqsq *sq)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = sq->channel->mdev;
|
||||
|
||||
if (!mlx5_accel_is_tls_device(mdev))
|
||||
return 0;
|
||||
|
||||
if (mlx5_accel_is_ktls_device(mdev))
|
||||
return mlx5e_ktls_get_stop_room(sq);
|
||||
|
||||
/* FPGA */
|
||||
/* Resync SKB. */
|
||||
return mlx5e_stop_room_for_wqe(MLX5_SEND_WQE_MAX_WQEBBS);
|
||||
}
|
||||
|
@ -34,23 +34,47 @@
|
||||
#ifndef __MLX5E_TLS_RXTX_H__
|
||||
#define __MLX5E_TLS_RXTX_H__
|
||||
|
||||
#include "accel/accel.h"
|
||||
#include "en_accel/ktls_txrx.h"
|
||||
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include "en.h"
|
||||
#include "en/txrx.h"
|
||||
|
||||
struct mlx5e_accel_tx_tls_state {
|
||||
u32 tls_tisn;
|
||||
};
|
||||
u16 mlx5e_tls_get_stop_room(struct mlx5e_txqsq *sq);
|
||||
|
||||
bool mlx5e_tls_handle_tx_skb(struct net_device *netdev, struct mlx5e_txqsq *sq,
|
||||
struct sk_buff *skb, struct mlx5e_accel_tx_tls_state *state);
|
||||
void mlx5e_tls_handle_tx_wqe(struct mlx5e_txqsq *sq, struct mlx5_wqe_ctrl_seg *cseg,
|
||||
struct mlx5e_accel_tx_tls_state *state);
|
||||
|
||||
void mlx5e_tls_handle_rx_skb(struct net_device *netdev, struct sk_buff *skb,
|
||||
u32 *cqe_bcnt);
|
||||
void mlx5e_tls_handle_rx_skb_metadata(struct mlx5e_rq *rq, struct sk_buff *skb,
|
||||
u32 *cqe_bcnt);
|
||||
|
||||
static inline void
|
||||
mlx5e_tls_handle_rx_skb(struct mlx5e_rq *rq, struct sk_buff *skb,
|
||||
struct mlx5_cqe64 *cqe, u32 *cqe_bcnt)
|
||||
{
|
||||
if (unlikely(get_cqe_tls_offload(cqe))) /* cqe bit indicates a TLS device */
|
||||
return mlx5e_ktls_handle_rx_skb(rq, skb, cqe, cqe_bcnt);
|
||||
|
||||
if (unlikely(test_bit(MLX5E_RQ_STATE_FPGA_TLS, &rq->state) && is_metadata_hdr_valid(skb)))
|
||||
return mlx5e_tls_handle_rx_skb_metadata(rq, skb, cqe_bcnt);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline bool
|
||||
mlx5e_accel_is_tls(struct mlx5_cqe64 *cqe, struct sk_buff *skb) { return false; }
|
||||
static inline void
|
||||
mlx5e_tls_handle_rx_skb(struct mlx5e_rq *rq, struct sk_buff *skb,
|
||||
struct mlx5_cqe64 *cqe, u32 *cqe_bcnt) {}
|
||||
static inline u16 mlx5e_tls_get_stop_room(struct mlx5e_txqsq *sq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MLX5_EN_TLS */
|
||||
|
||||
|
@ -90,23 +90,15 @@ static enum mlx5e_traffic_types arfs_get_tt(enum arfs_type type)
|
||||
|
||||
static int arfs_disable(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5_flow_destination dest = {};
|
||||
struct mlx5e_tir *tir = priv->indir_tir;
|
||||
int err = 0;
|
||||
int tt;
|
||||
int i;
|
||||
int err, i;
|
||||
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
|
||||
for (i = 0; i < ARFS_NUM_TYPES; i++) {
|
||||
dest.tir_num = tir[i].tirn;
|
||||
tt = arfs_get_tt(i);
|
||||
/* Modify ttc rules destination to bypass the aRFS tables*/
|
||||
err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt],
|
||||
&dest, NULL);
|
||||
/* Modify ttc rules destination back to their default */
|
||||
err = mlx5e_ttc_fwd_default_dest(priv, arfs_get_tt(i));
|
||||
if (err) {
|
||||
netdev_err(priv->netdev,
|
||||
"%s: modify ttc destination failed\n",
|
||||
__func__);
|
||||
"%s: modify ttc[%d] default destination failed, err(%d)\n",
|
||||
__func__, arfs_get_tt(i), err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -125,21 +117,17 @@ int mlx5e_arfs_disable(struct mlx5e_priv *priv)
|
||||
int mlx5e_arfs_enable(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5_flow_destination dest = {};
|
||||
int err = 0;
|
||||
int tt;
|
||||
int i;
|
||||
int err, i;
|
||||
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||
for (i = 0; i < ARFS_NUM_TYPES; i++) {
|
||||
dest.ft = priv->fs.arfs.arfs_tables[i].ft.t;
|
||||
tt = arfs_get_tt(i);
|
||||
/* Modify ttc rules destination to point on the aRFS FTs */
|
||||
err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt],
|
||||
&dest, NULL);
|
||||
err = mlx5e_ttc_fwd_dest(priv, arfs_get_tt(i), &dest);
|
||||
if (err) {
|
||||
netdev_err(priv->netdev,
|
||||
"%s: modify ttc destination failed err=%d\n",
|
||||
__func__, err);
|
||||
"%s: modify ttc[%d] dest to arfs, failed err(%d)\n",
|
||||
__func__, arfs_get_tt(i), err);
|
||||
arfs_disable(priv);
|
||||
return err;
|
||||
}
|
||||
@ -186,8 +174,10 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* FIXME: Must use mlx5e_ttc_get_default_dest(),
|
||||
* but can't since TTC default is not setup yet !
|
||||
*/
|
||||
dest.tir_num = tir[tt].tirn;
|
||||
|
||||
arfs_t->default_rule = mlx5_add_flow_rules(arfs_t->ft.t, NULL,
|
||||
&flow_act,
|
||||
&dest, 1);
|
||||
|
@ -672,9 +672,9 @@ static void mlx5e_cleanup_ttc_rules(struct mlx5e_ttc_table *ttc)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MLX5E_NUM_TT; i++) {
|
||||
if (!IS_ERR_OR_NULL(ttc->rules[i])) {
|
||||
mlx5_del_flow_rules(ttc->rules[i]);
|
||||
ttc->rules[i] = NULL;
|
||||
if (!IS_ERR_OR_NULL(ttc->rules[i].rule)) {
|
||||
mlx5_del_flow_rules(ttc->rules[i].rule);
|
||||
ttc->rules[i].rule = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -857,7 +857,8 @@ static int mlx5e_generate_ttc_table_rules(struct mlx5e_priv *priv,
|
||||
struct mlx5e_ttc_table *ttc)
|
||||
{
|
||||
struct mlx5_flow_destination dest = {};
|
||||
struct mlx5_flow_handle **rules;
|
||||
struct mlx5_flow_handle **trules;
|
||||
struct mlx5e_ttc_rule *rules;
|
||||
struct mlx5_flow_table *ft;
|
||||
int tt;
|
||||
int err;
|
||||
@ -867,39 +868,47 @@ static int mlx5e_generate_ttc_table_rules(struct mlx5e_priv *priv,
|
||||
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
|
||||
for (tt = 0; tt < MLX5E_NUM_TT; tt++) {
|
||||
struct mlx5e_ttc_rule *rule = &rules[tt];
|
||||
|
||||
if (tt == MLX5E_TT_ANY)
|
||||
dest.tir_num = params->any_tt_tirn;
|
||||
else
|
||||
dest.tir_num = params->indir_tirn[tt];
|
||||
rules[tt] = mlx5e_generate_ttc_rule(priv, ft, &dest,
|
||||
ttc_rules[tt].etype,
|
||||
ttc_rules[tt].proto);
|
||||
if (IS_ERR(rules[tt]))
|
||||
|
||||
rule->rule = mlx5e_generate_ttc_rule(priv, ft, &dest,
|
||||
ttc_rules[tt].etype,
|
||||
ttc_rules[tt].proto);
|
||||
if (IS_ERR(rule->rule)) {
|
||||
err = PTR_ERR(rule->rule);
|
||||
rule->rule = NULL;
|
||||
goto del_rules;
|
||||
}
|
||||
rule->default_dest = dest;
|
||||
}
|
||||
|
||||
if (!params->inner_ttc || !mlx5e_tunnel_inner_ft_supported(priv->mdev))
|
||||
return 0;
|
||||
|
||||
rules = ttc->tunnel_rules;
|
||||
trules = ttc->tunnel_rules;
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||
dest.ft = params->inner_ttc->ft.t;
|
||||
for (tt = 0; tt < MLX5E_NUM_TUNNEL_TT; tt++) {
|
||||
if (!mlx5e_tunnel_proto_supported(priv->mdev,
|
||||
ttc_tunnel_rules[tt].proto))
|
||||
continue;
|
||||
rules[tt] = mlx5e_generate_ttc_rule(priv, ft, &dest,
|
||||
ttc_tunnel_rules[tt].etype,
|
||||
ttc_tunnel_rules[tt].proto);
|
||||
if (IS_ERR(rules[tt]))
|
||||
trules[tt] = mlx5e_generate_ttc_rule(priv, ft, &dest,
|
||||
ttc_tunnel_rules[tt].etype,
|
||||
ttc_tunnel_rules[tt].proto);
|
||||
if (IS_ERR(trules[tt])) {
|
||||
err = PTR_ERR(trules[tt]);
|
||||
trules[tt] = NULL;
|
||||
goto del_rules;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
del_rules:
|
||||
err = PTR_ERR(rules[tt]);
|
||||
rules[tt] = NULL;
|
||||
mlx5e_cleanup_ttc_rules(ttc);
|
||||
return err;
|
||||
}
|
||||
@ -1015,33 +1024,38 @@ static int mlx5e_generate_inner_ttc_table_rules(struct mlx5e_priv *priv,
|
||||
struct mlx5e_ttc_table *ttc)
|
||||
{
|
||||
struct mlx5_flow_destination dest = {};
|
||||
struct mlx5_flow_handle **rules;
|
||||
struct mlx5e_ttc_rule *rules;
|
||||
struct mlx5_flow_table *ft;
|
||||
int err;
|
||||
int tt;
|
||||
|
||||
ft = ttc->ft.t;
|
||||
rules = ttc->rules;
|
||||
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
|
||||
|
||||
for (tt = 0; tt < MLX5E_NUM_TT; tt++) {
|
||||
struct mlx5e_ttc_rule *rule = &rules[tt];
|
||||
|
||||
if (tt == MLX5E_TT_ANY)
|
||||
dest.tir_num = params->any_tt_tirn;
|
||||
else
|
||||
dest.tir_num = params->indir_tirn[tt];
|
||||
|
||||
rules[tt] = mlx5e_generate_inner_ttc_rule(priv, ft, &dest,
|
||||
ttc_rules[tt].etype,
|
||||
ttc_rules[tt].proto);
|
||||
if (IS_ERR(rules[tt]))
|
||||
rule->rule = mlx5e_generate_inner_ttc_rule(priv, ft, &dest,
|
||||
ttc_rules[tt].etype,
|
||||
ttc_rules[tt].proto);
|
||||
if (IS_ERR(rule->rule)) {
|
||||
err = PTR_ERR(rule->rule);
|
||||
rule->rule = NULL;
|
||||
goto del_rules;
|
||||
}
|
||||
rule->default_dest = dest;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
del_rules:
|
||||
err = PTR_ERR(rules[tt]);
|
||||
rules[tt] = NULL;
|
||||
|
||||
mlx5e_cleanup_ttc_rules(ttc);
|
||||
return err;
|
||||
}
|
||||
@ -1210,6 +1224,30 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5e_ttc_fwd_dest(struct mlx5e_priv *priv, enum mlx5e_traffic_types type,
|
||||
struct mlx5_flow_destination *new_dest)
|
||||
{
|
||||
return mlx5_modify_rule_destination(priv->fs.ttc.rules[type].rule, new_dest, NULL);
|
||||
}
|
||||
|
||||
struct mlx5_flow_destination
|
||||
mlx5e_ttc_get_default_dest(struct mlx5e_priv *priv, enum mlx5e_traffic_types type)
|
||||
{
|
||||
struct mlx5_flow_destination *dest = &priv->fs.ttc.rules[type].default_dest;
|
||||
|
||||
WARN_ONCE(dest->type != MLX5_FLOW_DESTINATION_TYPE_TIR,
|
||||
"TTC[%d] default dest is not setup yet", type);
|
||||
|
||||
return *dest;
|
||||
}
|
||||
|
||||
int mlx5e_ttc_fwd_default_dest(struct mlx5e_priv *priv, enum mlx5e_traffic_types type)
|
||||
{
|
||||
struct mlx5_flow_destination dest = mlx5e_ttc_get_default_dest(priv, type);
|
||||
|
||||
return mlx5e_ttc_fwd_dest(priv, type, &dest);
|
||||
}
|
||||
|
||||
static void mlx5e_del_l2_flow_rule(struct mlx5e_priv *priv,
|
||||
struct mlx5e_l2_rule *ai)
|
||||
{
|
||||
|
@ -873,6 +873,9 @@ int mlx5e_open_rq(struct mlx5e_channel *c, struct mlx5e_params *params,
|
||||
if (err)
|
||||
goto err_destroy_rq;
|
||||
|
||||
if (mlx5e_is_tls_on(c->priv) && !mlx5_accel_is_ktls_device(c->mdev))
|
||||
__set_bit(MLX5E_RQ_STATE_FPGA_TLS, &c->rq.state); /* must be FPGA */
|
||||
|
||||
if (MLX5_CAP_ETH(c->mdev, cqe_checksum_full))
|
||||
__set_bit(MLX5E_RQ_STATE_CSUM_FULL, &c->rq.state);
|
||||
|
||||
@ -1441,6 +1444,7 @@ void mlx5e_close_icosq(struct mlx5e_icosq *sq)
|
||||
struct mlx5e_channel *c = sq->channel;
|
||||
|
||||
mlx5e_destroy_sq(c->mdev, sq->sqn);
|
||||
mlx5e_free_icosq_descs(sq);
|
||||
mlx5e_free_icosq(sq);
|
||||
}
|
||||
|
||||
@ -1675,7 +1679,7 @@ static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
|
||||
|
||||
for (tc = 0; tc < c->num_tc; tc++) {
|
||||
err = mlx5e_open_cq(c, params->tx_cq_moderation,
|
||||
&cparam->tx_cq, &c->sq[tc].cq);
|
||||
&cparam->txq_sq.cqp, &c->sq[tc].cq);
|
||||
if (err)
|
||||
goto err_close_tx_cqs;
|
||||
}
|
||||
@ -1707,7 +1711,7 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c,
|
||||
int txq_ix = c->ix + tc * params->num_channels;
|
||||
|
||||
err = mlx5e_open_txqsq(c, c->priv->tisn[c->lag_port][tc], txq_ix,
|
||||
params, &cparam->sq, &c->sq[tc], tc);
|
||||
params, &cparam->txq_sq, &c->sq[tc], tc);
|
||||
if (err)
|
||||
goto err_close_sqs;
|
||||
}
|
||||
@ -1817,34 +1821,43 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
|
||||
struct dim_cq_moder icocq_moder = {0, 0};
|
||||
int err;
|
||||
|
||||
err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq_cq, &c->icosq.cq);
|
||||
err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq.cqp, &c->async_icosq.cq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mlx5e_open_cq(c, icocq_moder, &cparam->async_icosq.cqp, &c->icosq.cq);
|
||||
if (err)
|
||||
goto err_close_async_icosq_cq;
|
||||
|
||||
err = mlx5e_open_tx_cqs(c, params, cparam);
|
||||
if (err)
|
||||
goto err_close_icosq_cq;
|
||||
|
||||
err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam->tx_cq, &c->xdpsq.cq);
|
||||
err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &c->xdpsq.cq);
|
||||
if (err)
|
||||
goto err_close_tx_cqs;
|
||||
|
||||
err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rx_cq, &c->rq.cq);
|
||||
err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rq.cqp, &c->rq.cq);
|
||||
if (err)
|
||||
goto err_close_xdp_tx_cqs;
|
||||
|
||||
/* XDP SQ CQ params are same as normal TXQ sq CQ params */
|
||||
err = c->xdp ? mlx5e_open_cq(c, params->tx_cq_moderation,
|
||||
&cparam->tx_cq, &c->rq_xdpsq.cq) : 0;
|
||||
&cparam->xdp_sq.cqp, &c->rq_xdpsq.cq) : 0;
|
||||
if (err)
|
||||
goto err_close_rx_cq;
|
||||
|
||||
napi_enable(&c->napi);
|
||||
|
||||
err = mlx5e_open_icosq(c, params, &cparam->icosq, &c->icosq);
|
||||
spin_lock_init(&c->async_icosq_lock);
|
||||
|
||||
err = mlx5e_open_icosq(c, params, &cparam->async_icosq, &c->async_icosq);
|
||||
if (err)
|
||||
goto err_disable_napi;
|
||||
|
||||
err = mlx5e_open_icosq(c, params, &cparam->icosq, &c->icosq);
|
||||
if (err)
|
||||
goto err_close_async_icosq;
|
||||
|
||||
err = mlx5e_open_sqs(c, params, cparam);
|
||||
if (err)
|
||||
goto err_close_icosq;
|
||||
@ -1879,6 +1892,9 @@ err_close_sqs:
|
||||
err_close_icosq:
|
||||
mlx5e_close_icosq(&c->icosq);
|
||||
|
||||
err_close_async_icosq:
|
||||
mlx5e_close_icosq(&c->async_icosq);
|
||||
|
||||
err_disable_napi:
|
||||
napi_disable(&c->napi);
|
||||
|
||||
@ -1897,6 +1913,9 @@ err_close_tx_cqs:
|
||||
err_close_icosq_cq:
|
||||
mlx5e_close_cq(&c->icosq.cq);
|
||||
|
||||
err_close_async_icosq_cq:
|
||||
mlx5e_close_cq(&c->async_icosq.cq);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1908,6 +1927,7 @@ static void mlx5e_close_queues(struct mlx5e_channel *c)
|
||||
mlx5e_close_xdpsq(&c->rq_xdpsq);
|
||||
mlx5e_close_sqs(c);
|
||||
mlx5e_close_icosq(&c->icosq);
|
||||
mlx5e_close_icosq(&c->async_icosq);
|
||||
napi_disable(&c->napi);
|
||||
if (c->xdp)
|
||||
mlx5e_close_cq(&c->rq_xdpsq.cq);
|
||||
@ -1915,6 +1935,7 @@ static void mlx5e_close_queues(struct mlx5e_channel *c)
|
||||
mlx5e_close_cq(&c->xdpsq.cq);
|
||||
mlx5e_close_tx_cqs(c);
|
||||
mlx5e_close_cq(&c->icosq.cq);
|
||||
mlx5e_close_cq(&c->async_icosq.cq);
|
||||
}
|
||||
|
||||
static u8 mlx5e_enumerate_lag_port(struct mlx5_core_dev *mdev, int ix)
|
||||
@ -1995,6 +2016,7 @@ static void mlx5e_activate_channel(struct mlx5e_channel *c)
|
||||
for (tc = 0; tc < c->num_tc; tc++)
|
||||
mlx5e_activate_txqsq(&c->sq[tc]);
|
||||
mlx5e_activate_icosq(&c->icosq);
|
||||
mlx5e_activate_icosq(&c->async_icosq);
|
||||
mlx5e_activate_rq(&c->rq);
|
||||
|
||||
if (test_bit(MLX5E_CHANNEL_STATE_XSK, c->state))
|
||||
@ -2009,6 +2031,7 @@ static void mlx5e_deactivate_channel(struct mlx5e_channel *c)
|
||||
mlx5e_deactivate_xsk(c);
|
||||
|
||||
mlx5e_deactivate_rq(&c->rq);
|
||||
mlx5e_deactivate_icosq(&c->async_icosq);
|
||||
mlx5e_deactivate_icosq(&c->icosq);
|
||||
for (tc = 0; tc < c->num_tc; tc++)
|
||||
mlx5e_deactivate_txqsq(&c->sq[tc]);
|
||||
@ -2138,6 +2161,7 @@ void mlx5e_build_rq_param(struct mlx5e_priv *priv,
|
||||
MLX5_SET(rqc, rqc, scatter_fcs, params->scatter_fcs_en);
|
||||
|
||||
param->wq.buf_numa_node = dev_to_node(mdev->device);
|
||||
mlx5e_build_rx_cq_param(priv, params, xsk, ¶m->cqp);
|
||||
}
|
||||
|
||||
static void mlx5e_build_drop_rq_param(struct mlx5e_priv *priv,
|
||||
@ -2180,6 +2204,7 @@ static void mlx5e_build_sq_param(struct mlx5e_priv *priv,
|
||||
mlx5e_build_sq_param_common(priv, param);
|
||||
MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size);
|
||||
MLX5_SET(sqc, sqc, allow_swp, allow_swp);
|
||||
mlx5e_build_tx_cq_param(priv, params, ¶m->cqp);
|
||||
}
|
||||
|
||||
static void mlx5e_build_common_cq_param(struct mlx5e_priv *priv,
|
||||
@ -2256,6 +2281,7 @@ void mlx5e_build_icosq_param(struct mlx5e_priv *priv,
|
||||
|
||||
MLX5_SET(wq, wq, log_wq_sz, log_wq_size);
|
||||
MLX5_SET(sqc, sqc, reg_umr, MLX5_CAP_ETH(priv->mdev, reg_umr_sq));
|
||||
mlx5e_build_ico_cq_param(priv, log_wq_size, ¶m->cqp);
|
||||
}
|
||||
|
||||
void mlx5e_build_xdpsq_param(struct mlx5e_priv *priv,
|
||||
@ -2268,6 +2294,7 @@ void mlx5e_build_xdpsq_param(struct mlx5e_priv *priv,
|
||||
mlx5e_build_sq_param_common(priv, param);
|
||||
MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size);
|
||||
param->is_mpw = MLX5E_GET_PFLAG(params, MLX5E_PFLAG_XDP_TX_MPWQE);
|
||||
mlx5e_build_tx_cq_param(priv, params, ¶m->cqp);
|
||||
}
|
||||
|
||||
static u8 mlx5e_build_icosq_log_wq_sz(struct mlx5e_params *params,
|
||||
@ -2282,22 +2309,29 @@ static u8 mlx5e_build_icosq_log_wq_sz(struct mlx5e_params *params,
|
||||
}
|
||||
}
|
||||
|
||||
static u8 mlx5e_build_async_icosq_log_wq_sz(struct net_device *netdev)
|
||||
{
|
||||
if (netdev->hw_features & NETIF_F_HW_TLS_RX)
|
||||
return MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
|
||||
|
||||
return MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
|
||||
}
|
||||
|
||||
static void mlx5e_build_channel_param(struct mlx5e_priv *priv,
|
||||
struct mlx5e_params *params,
|
||||
struct mlx5e_channel_param *cparam)
|
||||
{
|
||||
u8 icosq_log_wq_sz;
|
||||
u8 icosq_log_wq_sz, async_icosq_log_wq_sz;
|
||||
|
||||
mlx5e_build_rq_param(priv, params, NULL, &cparam->rq);
|
||||
|
||||
icosq_log_wq_sz = mlx5e_build_icosq_log_wq_sz(params, &cparam->rq);
|
||||
async_icosq_log_wq_sz = mlx5e_build_async_icosq_log_wq_sz(priv->netdev);
|
||||
|
||||
mlx5e_build_sq_param(priv, params, &cparam->sq);
|
||||
mlx5e_build_sq_param(priv, params, &cparam->txq_sq);
|
||||
mlx5e_build_xdpsq_param(priv, params, &cparam->xdp_sq);
|
||||
mlx5e_build_icosq_param(priv, icosq_log_wq_sz, &cparam->icosq);
|
||||
mlx5e_build_rx_cq_param(priv, params, NULL, &cparam->rx_cq);
|
||||
mlx5e_build_tx_cq_param(priv, params, &cparam->tx_cq);
|
||||
mlx5e_build_ico_cq_param(priv, icosq_log_wq_sz, &cparam->icosq_cq);
|
||||
mlx5e_build_icosq_param(priv, async_icosq_log_wq_sz, &cparam->async_icosq);
|
||||
}
|
||||
|
||||
int mlx5e_open_channels(struct mlx5e_priv *priv,
|
||||
@ -3831,6 +3865,7 @@ int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
|
||||
#ifdef CONFIG_MLX5_EN_ARFS
|
||||
err |= MLX5E_HANDLE_FEATURE(NETIF_F_NTUPLE, set_feature_arfs);
|
||||
#endif
|
||||
err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TLS_RX, mlx5e_ktls_set_feature_rx);
|
||||
|
||||
if (err) {
|
||||
netdev->features = oper_features;
|
||||
@ -5121,8 +5156,14 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
|
||||
if (err)
|
||||
goto err_destroy_flow_steering;
|
||||
|
||||
err = mlx5e_accel_init_rx(priv);
|
||||
if (err)
|
||||
goto err_tc_nic_cleanup;
|
||||
|
||||
return 0;
|
||||
|
||||
err_tc_nic_cleanup:
|
||||
mlx5e_tc_nic_cleanup(priv);
|
||||
err_destroy_flow_steering:
|
||||
mlx5e_destroy_flow_steering(priv);
|
||||
err_destroy_xsk_tirs:
|
||||
@ -5146,6 +5187,7 @@ err_destroy_q_counters:
|
||||
|
||||
static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
|
||||
{
|
||||
mlx5e_accel_cleanup_rx(priv);
|
||||
mlx5e_tc_nic_cleanup(priv);
|
||||
mlx5e_destroy_flow_steering(priv);
|
||||
mlx5e_destroy_direct_tirs(priv, priv->xsk_tir);
|
||||
|
@ -578,6 +578,33 @@ bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq)
|
||||
return !!err;
|
||||
}
|
||||
|
||||
void mlx5e_free_icosq_descs(struct mlx5e_icosq *sq)
|
||||
{
|
||||
u16 sqcc;
|
||||
|
||||
sqcc = sq->cc;
|
||||
|
||||
while (sqcc != sq->pc) {
|
||||
struct mlx5e_icosq_wqe_info *wi;
|
||||
u16 ci;
|
||||
|
||||
ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sqcc);
|
||||
wi = &sq->db.wqe_info[ci];
|
||||
sqcc += wi->num_wqebbs;
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
switch (wi->wqe_type) {
|
||||
case MLX5E_ICOSQ_WQE_SET_PSV_TLS:
|
||||
mlx5e_ktls_handle_ctx_completion(wi);
|
||||
break;
|
||||
case MLX5E_ICOSQ_WQE_GET_PSV_TLS:
|
||||
mlx5e_ktls_handle_get_psv_completion(wi, sq);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sq->cc = sqcc;
|
||||
}
|
||||
|
||||
int mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
|
||||
{
|
||||
struct mlx5e_icosq *sq = container_of(cq, struct mlx5e_icosq, cq);
|
||||
@ -633,6 +660,16 @@ int mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
|
||||
break;
|
||||
case MLX5E_ICOSQ_WQE_NOP:
|
||||
break;
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
case MLX5E_ICOSQ_WQE_UMR_TLS:
|
||||
break;
|
||||
case MLX5E_ICOSQ_WQE_SET_PSV_TLS:
|
||||
mlx5e_ktls_handle_ctx_completion(wi);
|
||||
break;
|
||||
case MLX5E_ICOSQ_WQE_GET_PSV_TLS:
|
||||
mlx5e_ktls_handle_get_psv_completion(wi, sq);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
netdev_WARN_ONCE(cq->channel->netdev,
|
||||
"Bad WQE type in ICOSQ WQE info: 0x%x\n",
|
||||
@ -982,9 +1019,7 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
|
||||
|
||||
skb->mac_len = ETH_HLEN;
|
||||
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
mlx5e_tls_handle_rx_skb(netdev, skb, &cqe_bcnt);
|
||||
#endif
|
||||
mlx5e_tls_handle_rx_skb(rq, skb, cqe, &cqe_bcnt);
|
||||
|
||||
if (lro_num_seg > 1) {
|
||||
mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt);
|
||||
|
@ -163,6 +163,19 @@ static const struct counter_desc sw_stats_desc[] = {
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_congst_umr) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_arfs_err) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_recover) },
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_decrypted_packets) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_decrypted_bytes) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_ctx) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_del) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_req_pkt) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_req_start) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_req_end) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_req_skip) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_res_ok) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_res_skip) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_err) },
|
||||
#endif
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, ch_events) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, ch_poll) },
|
||||
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, ch_arm) },
|
||||
@ -275,6 +288,19 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(sw)
|
||||
s->rx_congst_umr += rq_stats->congst_umr;
|
||||
s->rx_arfs_err += rq_stats->arfs_err;
|
||||
s->rx_recover += rq_stats->recover;
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
s->rx_tls_decrypted_packets += rq_stats->tls_decrypted_packets;
|
||||
s->rx_tls_decrypted_bytes += rq_stats->tls_decrypted_bytes;
|
||||
s->rx_tls_ctx += rq_stats->tls_ctx;
|
||||
s->rx_tls_del += rq_stats->tls_del;
|
||||
s->rx_tls_resync_req_pkt += rq_stats->tls_resync_req_pkt;
|
||||
s->rx_tls_resync_req_start += rq_stats->tls_resync_req_start;
|
||||
s->rx_tls_resync_req_end += rq_stats->tls_resync_req_end;
|
||||
s->rx_tls_resync_req_skip += rq_stats->tls_resync_req_skip;
|
||||
s->rx_tls_resync_res_ok += rq_stats->tls_resync_res_ok;
|
||||
s->rx_tls_resync_res_skip += rq_stats->tls_resync_res_skip;
|
||||
s->rx_tls_err += rq_stats->tls_err;
|
||||
#endif
|
||||
s->ch_events += ch_stats->events;
|
||||
s->ch_poll += ch_stats->poll;
|
||||
s->ch_arm += ch_stats->arm;
|
||||
@ -1475,6 +1501,19 @@ static const struct counter_desc rq_stats_desc[] = {
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, congst_umr) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, arfs_err) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, recover) },
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_decrypted_packets) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_decrypted_bytes) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_ctx) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_del) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_req_pkt) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_req_start) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_req_end) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_req_skip) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_res_ok) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_res_skip) },
|
||||
{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_err) },
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct counter_desc sq_stats_desc[] = {
|
||||
|
@ -186,6 +186,18 @@ struct mlx5e_sw_stats {
|
||||
u64 tx_tls_skip_no_sync_data;
|
||||
u64 tx_tls_drop_no_sync_data;
|
||||
u64 tx_tls_drop_bypass_req;
|
||||
|
||||
u64 rx_tls_decrypted_packets;
|
||||
u64 rx_tls_decrypted_bytes;
|
||||
u64 rx_tls_ctx;
|
||||
u64 rx_tls_del;
|
||||
u64 rx_tls_resync_req_pkt;
|
||||
u64 rx_tls_resync_req_start;
|
||||
u64 rx_tls_resync_req_end;
|
||||
u64 rx_tls_resync_req_skip;
|
||||
u64 rx_tls_resync_res_ok;
|
||||
u64 rx_tls_resync_res_skip;
|
||||
u64 rx_tls_err;
|
||||
#endif
|
||||
|
||||
u64 rx_xsk_packets;
|
||||
@ -305,6 +317,19 @@ struct mlx5e_rq_stats {
|
||||
u64 congst_umr;
|
||||
u64 arfs_err;
|
||||
u64 recover;
|
||||
#ifdef CONFIG_MLX5_EN_TLS
|
||||
u64 tls_decrypted_packets;
|
||||
u64 tls_decrypted_bytes;
|
||||
u64 tls_ctx;
|
||||
u64 tls_del;
|
||||
u64 tls_resync_req_pkt;
|
||||
u64 tls_resync_req_start;
|
||||
u64 tls_resync_req_end;
|
||||
u64 tls_resync_req_skip;
|
||||
u64 tls_resync_res_ok;
|
||||
u64 tls_resync_res_skip;
|
||||
u64 tls_err;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct mlx5e_sq_stats {
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "en/txrx.h"
|
||||
#include "ipoib/ipoib.h"
|
||||
#include "en_accel/en_accel.h"
|
||||
#include "en_accel/ktls.h"
|
||||
#include "lib/clock.h"
|
||||
|
||||
static void mlx5e_dma_unmap_wqe_err(struct mlx5e_txqsq *sq, u8 num_dma)
|
||||
|
@ -149,17 +149,17 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
|
||||
}
|
||||
|
||||
mlx5e_poll_ico_cq(&c->icosq.cq);
|
||||
if (mlx5e_poll_ico_cq(&c->async_icosq.cq))
|
||||
/* Don't clear the flag if nothing was polled to prevent
|
||||
* queueing more WQEs and overflowing the async ICOSQ.
|
||||
*/
|
||||
clear_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->async_icosq.state);
|
||||
|
||||
busy |= INDIRECT_CALL_2(rq->post_wqes,
|
||||
mlx5e_post_rx_mpwqes,
|
||||
mlx5e_post_rx_wqes,
|
||||
rq);
|
||||
if (xsk_open) {
|
||||
if (mlx5e_poll_ico_cq(&c->xskicosq.cq))
|
||||
/* Don't clear the flag if nothing was polled to prevent
|
||||
* queueing more WQEs and overflowing XSKICOSQ.
|
||||
*/
|
||||
clear_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->xskicosq.state);
|
||||
busy |= mlx5e_poll_xdpsq_cq(&xsksq->cq);
|
||||
busy_xsk |= mlx5e_napi_xsk_post(xsksq, xskrq);
|
||||
}
|
||||
@ -189,11 +189,11 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
|
||||
|
||||
mlx5e_cq_arm(&rq->cq);
|
||||
mlx5e_cq_arm(&c->icosq.cq);
|
||||
mlx5e_cq_arm(&c->async_icosq.cq);
|
||||
mlx5e_cq_arm(&c->xdpsq.cq);
|
||||
|
||||
if (xsk_open) {
|
||||
mlx5e_handle_rx_dim(xskrq);
|
||||
mlx5e_cq_arm(&c->xskicosq.cq);
|
||||
mlx5e_cq_arm(&xsksq->cq);
|
||||
mlx5e_cq_arm(&xskrq->cq);
|
||||
}
|
||||
|
@ -105,8 +105,8 @@
|
||||
#define ETHTOOL_PRIO_NUM_LEVELS 1
|
||||
#define ETHTOOL_NUM_PRIOS 11
|
||||
#define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS)
|
||||
/* Vlan, mac, ttc, inner ttc, aRFS */
|
||||
#define KERNEL_NIC_PRIO_NUM_LEVELS 5
|
||||
/* Vlan, mac, ttc, inner ttc, {aRFS/accel} */
|
||||
#define KERNEL_NIC_PRIO_NUM_LEVELS 6
|
||||
#define KERNEL_NIC_NUM_PRIOS 1
|
||||
/* One more level for tc */
|
||||
#define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <linux/module.h>
|
||||
#include "mlx5_core.h"
|
||||
#include "../../mlxfw/mlxfw.h"
|
||||
#include "accel/tls.h"
|
||||
|
||||
enum {
|
||||
MCQS_IDENTIFIER_BOOT_IMG = 0x1,
|
||||
@ -236,7 +237,7 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (MLX5_CAP_GEN(dev, tls_tx)) {
|
||||
if (mlx5_accel_is_ktls_tx(dev) || mlx5_accel_is_ktls_rx(dev)) {
|
||||
err = mlx5_core_get_caps(dev, MLX5_CAP_TLS);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -33,7 +33,6 @@
|
||||
#ifndef MLX5_CORE_CQ_H
|
||||
#define MLX5_CORE_CQ_H
|
||||
|
||||
#include <rdma/ib_verbs.h>
|
||||
#include <linux/mlx5/driver.h>
|
||||
#include <linux/refcount.h>
|
||||
|
||||
|
@ -458,6 +458,15 @@ enum {
|
||||
MLX5_OPC_MOD_TLS_TIR_PROGRESS_PARAMS = 0x2,
|
||||
};
|
||||
|
||||
struct mlx5_wqe_tls_static_params_seg {
|
||||
u8 ctx[MLX5_ST_SZ_BYTES(tls_static_params)];
|
||||
};
|
||||
|
||||
struct mlx5_wqe_tls_progress_params_seg {
|
||||
__be32 tis_tir_num;
|
||||
u8 ctx[MLX5_ST_SZ_BYTES(tls_progress_params)];
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_SET_PORT_RESET_QKEY = 0,
|
||||
MLX5_SET_PORT_GUID0 = 16,
|
||||
|
@ -10640,16 +10640,13 @@ struct mlx5_ifc_tls_static_params_bits {
|
||||
};
|
||||
|
||||
struct mlx5_ifc_tls_progress_params_bits {
|
||||
u8 reserved_at_0[0x8];
|
||||
u8 tisn[0x18];
|
||||
|
||||
u8 next_record_tcp_sn[0x20];
|
||||
|
||||
u8 hw_resync_tcp_sn[0x20];
|
||||
|
||||
u8 record_tracker_state[0x2];
|
||||
u8 auth_state[0x2];
|
||||
u8 reserved_at_64[0x4];
|
||||
u8 reserved_at_44[0x4];
|
||||
u8 hw_offset_record_number[0x18];
|
||||
};
|
||||
|
||||
|
@ -209,7 +209,7 @@ struct mlx5_wqe_ctrl_seg {
|
||||
__be32 general_id;
|
||||
__be32 imm;
|
||||
__be32 umr_mkey;
|
||||
__be32 tisn;
|
||||
__be32 tis_tir_num;
|
||||
};
|
||||
};
|
||||
|
||||
|
51
include/linux/mlx5/rsc_dump.h
Normal file
51
include/linux/mlx5/rsc_dump.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/* Copyright (c) 2020 Mellanox Technologies inc. */
|
||||
|
||||
#include <linux/mlx5/driver.h>
|
||||
|
||||
#ifndef __MLX5_RSC_DUMP
|
||||
#define __MLX5_RSC_DUMP
|
||||
|
||||
enum mlx5_sgmt_type {
|
||||
MLX5_SGMT_TYPE_HW_CQPC,
|
||||
MLX5_SGMT_TYPE_HW_SQPC,
|
||||
MLX5_SGMT_TYPE_HW_RQPC,
|
||||
MLX5_SGMT_TYPE_FULL_SRQC,
|
||||
MLX5_SGMT_TYPE_FULL_CQC,
|
||||
MLX5_SGMT_TYPE_FULL_EQC,
|
||||
MLX5_SGMT_TYPE_FULL_QPC,
|
||||
MLX5_SGMT_TYPE_SND_BUFF,
|
||||
MLX5_SGMT_TYPE_RCV_BUFF,
|
||||
MLX5_SGMT_TYPE_SRQ_BUFF,
|
||||
MLX5_SGMT_TYPE_CQ_BUFF,
|
||||
MLX5_SGMT_TYPE_EQ_BUFF,
|
||||
MLX5_SGMT_TYPE_SX_SLICE,
|
||||
MLX5_SGMT_TYPE_SX_SLICE_ALL,
|
||||
MLX5_SGMT_TYPE_RDB,
|
||||
MLX5_SGMT_TYPE_RX_SLICE_ALL,
|
||||
MLX5_SGMT_TYPE_PRM_QUERY_QP,
|
||||
MLX5_SGMT_TYPE_PRM_QUERY_CQ,
|
||||
MLX5_SGMT_TYPE_PRM_QUERY_MKEY,
|
||||
MLX5_SGMT_TYPE_MENU,
|
||||
MLX5_SGMT_TYPE_TERMINATE,
|
||||
|
||||
MLX5_SGMT_TYPE_NUM, /* Keep last */
|
||||
};
|
||||
|
||||
struct mlx5_rsc_key {
|
||||
enum mlx5_sgmt_type rsc;
|
||||
int index1;
|
||||
int index2;
|
||||
int num_of_obj1;
|
||||
int num_of_obj2;
|
||||
int size;
|
||||
};
|
||||
|
||||
struct mlx5_rsc_dump_cmd;
|
||||
|
||||
struct mlx5_rsc_dump_cmd *mlx5_rsc_dump_cmd_create(struct mlx5_core_dev *dev,
|
||||
struct mlx5_rsc_key *key);
|
||||
void mlx5_rsc_dump_cmd_destroy(struct mlx5_rsc_dump_cmd *cmd);
|
||||
int mlx5_rsc_dump_next(struct mlx5_core_dev *dev, struct mlx5_rsc_dump_cmd *cmd,
|
||||
struct page *page, int *size);
|
||||
#endif /* __MLX5_RSC_DUMP */
|
@ -291,11 +291,19 @@ struct tlsdev_ops {
|
||||
enum tls_offload_sync_type {
|
||||
TLS_OFFLOAD_SYNC_TYPE_DRIVER_REQ = 0,
|
||||
TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT = 1,
|
||||
TLS_OFFLOAD_SYNC_TYPE_DRIVER_REQ_ASYNC = 2,
|
||||
};
|
||||
|
||||
#define TLS_DEVICE_RESYNC_NH_START_IVAL 2
|
||||
#define TLS_DEVICE_RESYNC_NH_MAX_IVAL 128
|
||||
|
||||
#define TLS_DEVICE_RESYNC_ASYNC_LOGMAX 13
|
||||
struct tls_offload_resync_async {
|
||||
atomic64_t req;
|
||||
u32 loglen;
|
||||
u32 log[TLS_DEVICE_RESYNC_ASYNC_LOGMAX];
|
||||
};
|
||||
|
||||
struct tls_offload_context_rx {
|
||||
/* sw must be the first member of tls_offload_context_rx */
|
||||
struct tls_sw_context_rx sw;
|
||||
@ -314,6 +322,10 @@ struct tls_offload_context_rx {
|
||||
u32 decrypted_failed;
|
||||
u32 decrypted_tgt;
|
||||
} resync_nh;
|
||||
/* TLS_OFFLOAD_SYNC_TYPE_DRIVER_REQ_ASYNC */
|
||||
struct {
|
||||
struct tls_offload_resync_async *resync_async;
|
||||
};
|
||||
};
|
||||
u8 driver_state[] __aligned(8);
|
||||
/* The TLS layer reserves room for driver specific state
|
||||
@ -606,9 +618,9 @@ tls_driver_ctx(const struct sock *sk, enum tls_offload_ctx_dir direction)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RESYNC_REQ BIT(0)
|
||||
#define RESYNC_REQ_ASYNC BIT(1)
|
||||
/* The TLS context is valid until sk_destruct is called */
|
||||
#define RESYNC_REQ (1 << 0)
|
||||
#define RESYNC_REQ_FORCE (1 << 1)
|
||||
static inline void tls_offload_rx_resync_request(struct sock *sk, __be32 seq)
|
||||
{
|
||||
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
||||
@ -617,12 +629,26 @@ static inline void tls_offload_rx_resync_request(struct sock *sk, __be32 seq)
|
||||
atomic64_set(&rx_ctx->resync_req, ((u64)ntohl(seq) << 32) | RESYNC_REQ);
|
||||
}
|
||||
|
||||
static inline void tls_offload_rx_force_resync_request(struct sock *sk)
|
||||
/* Log all TLS record header TCP sequences in [seq, seq+len] */
|
||||
static inline void
|
||||
tls_offload_rx_resync_async_request_start(struct sock *sk, __be32 seq, u16 len)
|
||||
{
|
||||
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
||||
struct tls_offload_context_rx *rx_ctx = tls_offload_ctx_rx(tls_ctx);
|
||||
|
||||
atomic64_set(&rx_ctx->resync_req, RESYNC_REQ | RESYNC_REQ_FORCE);
|
||||
atomic64_set(&rx_ctx->resync_async->req, ((u64)ntohl(seq) << 32) |
|
||||
(len << 16) | RESYNC_REQ | RESYNC_REQ_ASYNC);
|
||||
rx_ctx->resync_async->loglen = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tls_offload_rx_resync_async_request_end(struct sock *sk, __be32 seq)
|
||||
{
|
||||
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
||||
struct tls_offload_context_rx *rx_ctx = tls_offload_ctx_rx(tls_ctx);
|
||||
|
||||
atomic64_set(&rx_ctx->resync_async->req,
|
||||
((u64)ntohl(seq) << 32) | RESYNC_REQ);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -690,15 +690,55 @@ static void tls_device_resync_rx(struct tls_context *tls_ctx,
|
||||
TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXDEVICERESYNC);
|
||||
}
|
||||
|
||||
static bool
|
||||
tls_device_rx_resync_async(struct tls_offload_resync_async *resync_async,
|
||||
s64 resync_req, u32 *seq)
|
||||
{
|
||||
u32 is_async = resync_req & RESYNC_REQ_ASYNC;
|
||||
u32 req_seq = resync_req >> 32;
|
||||
u32 req_end = req_seq + ((resync_req >> 16) & 0xffff);
|
||||
|
||||
if (is_async) {
|
||||
/* asynchronous stage: log all headers seq such that
|
||||
* req_seq <= seq <= end_seq, and wait for real resync request
|
||||
*/
|
||||
if (between(*seq, req_seq, req_end) &&
|
||||
resync_async->loglen < TLS_DEVICE_RESYNC_ASYNC_LOGMAX)
|
||||
resync_async->log[resync_async->loglen++] = *seq;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* synchronous stage: check against the logged entries and
|
||||
* proceed to check the next entries if no match was found
|
||||
*/
|
||||
while (resync_async->loglen) {
|
||||
if (req_seq == resync_async->log[resync_async->loglen - 1] &&
|
||||
atomic64_try_cmpxchg(&resync_async->req,
|
||||
&resync_req, 0)) {
|
||||
resync_async->loglen = 0;
|
||||
*seq = req_seq;
|
||||
return true;
|
||||
}
|
||||
resync_async->loglen--;
|
||||
}
|
||||
|
||||
if (req_seq == *seq &&
|
||||
atomic64_try_cmpxchg(&resync_async->req,
|
||||
&resync_req, 0))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq)
|
||||
{
|
||||
struct tls_context *tls_ctx = tls_get_ctx(sk);
|
||||
struct tls_offload_context_rx *rx_ctx;
|
||||
bool is_req_pending, is_force_resync;
|
||||
u8 rcd_sn[TLS_MAX_REC_SEQ_SIZE];
|
||||
u32 sock_data, is_req_pending;
|
||||
struct tls_prot_info *prot;
|
||||
s64 resync_req;
|
||||
u32 sock_data;
|
||||
u32 req_seq;
|
||||
|
||||
if (tls_ctx->rx_conf != TLS_HW)
|
||||
@ -713,11 +753,9 @@ void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq)
|
||||
resync_req = atomic64_read(&rx_ctx->resync_req);
|
||||
req_seq = resync_req >> 32;
|
||||
seq += TLS_HEADER_SIZE - 1;
|
||||
is_req_pending = resync_req & RESYNC_REQ;
|
||||
is_force_resync = resync_req & RESYNC_REQ_FORCE;
|
||||
is_req_pending = resync_req;
|
||||
|
||||
if (likely(!is_req_pending) ||
|
||||
(!is_force_resync && req_seq != seq) ||
|
||||
if (likely(!is_req_pending) || req_seq != seq ||
|
||||
!atomic64_try_cmpxchg(&rx_ctx->resync_req, &resync_req, 0))
|
||||
return;
|
||||
break;
|
||||
@ -739,6 +777,16 @@ void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq)
|
||||
seq += rcd_len;
|
||||
tls_bigint_increment(rcd_sn, prot->rec_seq_size);
|
||||
break;
|
||||
case TLS_OFFLOAD_SYNC_TYPE_DRIVER_REQ_ASYNC:
|
||||
resync_req = atomic64_read(&rx_ctx->resync_async->req);
|
||||
is_req_pending = resync_req;
|
||||
if (likely(!is_req_pending))
|
||||
return;
|
||||
|
||||
if (!tls_device_rx_resync_async(rx_ctx->resync_async,
|
||||
resync_req, &seq))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
tls_device_resync_rx(tls_ctx, sk, seq, rcd_sn);
|
||||
|
Loading…
x
Reference in New Issue
Block a user