Commit 0dd1be4f authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'tls-introduce-and-use-rx-async-resync-request-cancel-function'

Tariq Toukan says:

====================
tls: Introduce and use RX async resync request cancel function

This series by Shahar introduces RX async resync request cancel function
in tls module, and uses it in mlx5e driver.

For a device-offloaded TLS RX connection, the TLS module increments
rcd_delta each time a new TLS record is received, tracking the distance
from the original resync request. In the meanwhile, the device is
queried and is expected to respond, asynchronously.

However, if the device response is delayed or fails (e.g due to unstable
connection and device getting out of tracking, hardware errors, resource
exhaustion etc.), the TLS module keeps logging and incrementing
rcd_delta, which can lead to a WARN() when rcd_delta exceeds the
threshold.

This series improves this code area by canceling the resync request when
spotting an issue with the device response.
====================

Link: https://patch.msgid.link/1761508983-937977-1-git-send-email-tariqt@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e98cda76 426e9da3
Loading
Loading
Loading
Loading
+35 −6
Original line number Diff line number Diff line
@@ -320,7 +320,6 @@ resync_post_get_progress_params(struct mlx5e_icosq *sq,
err_free:
	kfree(buf);
err_out:
	priv_rx->rq_stats->tls_resync_req_skip++;
	return err;
}

@@ -339,15 +338,20 @@ static void resync_handle_work(struct work_struct *work)

	if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) {
		mlx5e_ktls_priv_rx_put(priv_rx);
		priv_rx->rq_stats->tls_resync_req_skip++;
		tls_offload_rx_resync_async_request_cancel(&resync->core);
		return;
	}

	c = resync->priv->channels.c[priv_rx->rxq];
	sq = &c->async_icosq;

	if (resync_post_get_progress_params(sq, priv_rx))
	if (resync_post_get_progress_params(sq, priv_rx)) {
		priv_rx->rq_stats->tls_resync_req_skip++;
		tls_offload_rx_resync_async_request_cancel(&resync->core);
		mlx5e_ktls_priv_rx_put(priv_rx);
	}
}

static void resync_init(struct mlx5e_ktls_rx_resync_ctx *resync,
			struct mlx5e_priv *priv)
@@ -425,14 +429,21 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
{
	struct mlx5e_ktls_rx_resync_buf *buf = wi->tls_get_params.buf;
	struct mlx5e_ktls_offload_context_rx *priv_rx;
	struct tls_offload_resync_async *async_resync;
	struct tls_offload_context_rx *rx_ctx;
	u8 tracker_state, auth_state, *ctx;
	struct device *dev;
	u32 hw_seq;

	priv_rx = buf->priv_rx;
	dev = mlx5_core_dma_dev(sq->channel->mdev);
	if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags)))
	rx_ctx = tls_offload_ctx_rx(tls_get_ctx(priv_rx->sk));
	async_resync = rx_ctx->resync_async;
	if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags))) {
		priv_rx->rq_stats->tls_resync_req_skip++;
		tls_offload_rx_resync_async_request_cancel(async_resync);
		goto out;
	}

	dma_sync_single_for_cpu(dev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE,
				DMA_FROM_DEVICE);
@@ -443,11 +454,13 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
	if (tracker_state != MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING ||
	    auth_state != MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD) {
		priv_rx->rq_stats->tls_resync_req_skip++;
		tls_offload_rx_resync_async_request_cancel(async_resync);
		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));
	tls_offload_rx_resync_async_request_end(async_resync,
						cpu_to_be32(hw_seq));
	priv_rx->rq_stats->tls_resync_req_end++;
out:
	mlx5e_ktls_priv_rx_put(priv_rx);
@@ -472,8 +485,10 @@ static bool resync_queue_get_psv(struct sock *sk)

	resync = &priv_rx->resync;
	mlx5e_ktls_priv_rx_get(priv_rx);
	if (unlikely(!queue_work(resync->priv->tls->rx_wq, &resync->work)))
	if (unlikely(!queue_work(resync->priv->tls->rx_wq, &resync->work))) {
		mlx5e_ktls_priv_rx_put(priv_rx);
		return false;
	}

	return true;
}
@@ -482,6 +497,7 @@ static bool resync_queue_get_psv(struct sock *sk)
static void resync_update_sn(struct mlx5e_rq *rq, struct sk_buff *skb)
{
	struct ethhdr *eth = (struct ethhdr *)(skb->data);
	struct tls_offload_resync_async *resync_async;
	struct net_device *netdev = rq->netdev;
	struct net *net = dev_net(netdev);
	struct sock *sk = NULL;
@@ -527,7 +543,8 @@ static void resync_update_sn(struct mlx5e_rq *rq, struct sk_buff *skb)

	seq = th->seq;
	datalen = skb->len - depth;
	tls_offload_rx_resync_async_request_start(sk, seq, datalen);
	resync_async = tls_offload_ctx_rx(tls_get_ctx(sk))->resync_async;
	tls_offload_rx_resync_async_request_start(resync_async, seq, datalen);
	rq->stats->tls_resync_req_start++;

unref:
@@ -556,6 +573,18 @@ void mlx5e_ktls_rx_resync(struct net_device *netdev, struct sock *sk,
	resync_handle_seq_match(priv_rx, c);
}

void
mlx5e_ktls_rx_resync_async_request_cancel(struct mlx5e_icosq_wqe_info *wi)
{
	struct mlx5e_ktls_offload_context_rx *priv_rx;
	struct mlx5e_ktls_rx_resync_buf *buf;

	buf = wi->tls_get_params.buf;
	priv_rx = buf->priv_rx;
	priv_rx->rq_stats->tls_resync_req_skip++;
	tls_offload_rx_resync_async_request_cancel(&priv_rx->resync.core);
}

/* End of resync section */

void mlx5e_ktls_handle_rx_skb(struct mlx5e_rq *rq, struct sk_buff *skb,
+4 −0
Original line number Diff line number Diff line
@@ -29,6 +29,10 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
					   struct mlx5e_tx_wqe_info *wi,
					   u32 *dma_fifo_cc);

void
mlx5e_ktls_rx_resync_async_request_cancel(struct mlx5e_icosq_wqe_info *wi);

static inline bool
mlx5e_ktls_tx_try_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
					  struct mlx5e_tx_wqe_info *wi,
+4 −0
Original line number Diff line number Diff line
@@ -1036,6 +1036,10 @@ int mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
				netdev_WARN_ONCE(cq->netdev,
						 "Bad OP in ICOSQ CQE: 0x%x\n",
						 get_cqe_opcode(cqe));
#ifdef CONFIG_MLX5_EN_TLS
				if (wi->wqe_type == MLX5E_ICOSQ_WQE_GET_PSV_TLS)
					mlx5e_ktls_rx_resync_async_request_cancel(wi);
#endif
				mlx5e_dump_error_cqe(&sq->cq, sq->sqn,
						     (struct mlx5_err_cqe *)cqe);
				mlx5_wq_cyc_wqe_dump(&sq->wq, ci, wi->num_wqebbs);
+13 −12
Original line number Diff line number Diff line
@@ -451,25 +451,26 @@ static inline void tls_offload_rx_resync_request(struct sock *sk, __be32 seq)

/* 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)
tls_offload_rx_resync_async_request_start(struct tls_offload_resync_async *resync_async,
					  __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_async->req, ((u64)ntohl(seq) << 32) |
	atomic64_set(&resync_async->req, ((u64)ntohl(seq) << 32) |
		     ((u64)len << 16) | RESYNC_REQ | RESYNC_REQ_ASYNC);
	rx_ctx->resync_async->loglen = 0;
	rx_ctx->resync_async->rcd_delta = 0;
	resync_async->loglen = 0;
	resync_async->rcd_delta = 0;
}

static inline void
tls_offload_rx_resync_async_request_end(struct sock *sk, __be32 seq)
tls_offload_rx_resync_async_request_end(struct tls_offload_resync_async *resync_async,
					__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(&resync_async->req, ((u64)ntohl(seq) << 32) | RESYNC_REQ);
}

	atomic64_set(&rx_ctx->resync_async->req,
		     ((u64)ntohl(seq) << 32) | RESYNC_REQ);
static inline void
tls_offload_rx_resync_async_request_cancel(struct tls_offload_resync_async *resync_async)
{
	atomic64_set(&resync_async->req, 0);
}

static inline void
+3 −1
Original line number Diff line number Diff line
@@ -723,8 +723,10 @@ tls_device_rx_resync_async(struct tls_offload_resync_async *resync_async,
		/* shouldn't get to wraparound:
		 * too long in async stage, something bad happened
		 */
		if (WARN_ON_ONCE(resync_async->rcd_delta == USHRT_MAX))
		if (WARN_ON_ONCE(resync_async->rcd_delta == USHRT_MAX)) {
			tls_offload_rx_resync_async_request_cancel(resync_async);
			return false;
		}

		/* asynchronous stage: log all headers seq such that
		 * req_seq <= seq <= end_seq, and wait for real resync request