diff mbox series

[1/3] net/tls: Add asynchronous resync

Message ID 1617633096-165184-1-git-send-email-danielj@nvidia.com
State New
Headers show
Series [1/3] net/tls: Add asynchronous resync | expand

Commit Message

Daniel Jurgens April 5, 2021, 2:31 p.m. UTC
From: Boris Pismenny <borisp@mellanox.com>

This patch adds support for asynchronous resynchronization in tls_device.
Async resync follows two distinct stages:

1. 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.

2. 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.

Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
(cherry picked from commit ed9b7646b06a2ed2450dd9437fc7d1ad2783140c)
Signed-off-by: Daniel Jurgens <danielj@nvidia.com>
---
 include/net/tls.h    | 38 +++++++++++++++++++++++++++++++++++++-
 net/tls/tls_device.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 1 deletion(-)

Comments

Tim Gardner April 5, 2021, 2:47 p.m. UTC | #1
Hi Daniel - please resubmit with a subject line and SRU justification as 
described in https://wiki.ubuntu.com/Kernel/Dev/StablePatchFormat. Don't 
forget to add a BugLink to your patches. Its important to at least 
mention the kernel series (e.g., Focal) in the subject.

There are many examples for how to submit patches to this list in 
https://lists.ubuntu.com/archives/kernel-team/2021-April/thread.html

rtg

On 4/5/21 8:31 AM, Daniel Jurgens wrote:
> From: Boris Pismenny <borisp@mellanox.com>
> 
> This patch adds support for asynchronous resynchronization in tls_device.
> Async resync follows two distinct stages:
> 
> 1. 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.
> 
> 2. 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.
> 
> Signed-off-by: Boris Pismenny <borisp@mellanox.com>
> Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
> (cherry picked from commit ed9b7646b06a2ed2450dd9437fc7d1ad2783140c)
> Signed-off-by: Daniel Jurgens <danielj@nvidia.com>
> ---
>   include/net/tls.h    | 38 +++++++++++++++++++++++++++++++++++++-
>   net/tls/tls_device.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 88 insertions(+), 1 deletion(-)
> 
> diff --git a/include/net/tls.h b/include/net/tls.h
> index 697df45..e70dc8b 100644
> --- a/include/net/tls.h
> +++ b/include/net/tls.h
> @@ -319,11 +319,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;
> @@ -342,6 +350,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
> @@ -631,13 +643,37 @@ static inline void *__tls_driver_ctx(struct tls_context *tls_ctx,
>   }
>   #endif
>   
> +#define RESYNC_REQ BIT(0)
> +#define RESYNC_REQ_ASYNC BIT(1)
>   /* The TLS context is valid until sk_destruct is called */
>   static inline void tls_offload_rx_resync_request(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_req, ((u64)ntohl(seq) << 32) | 1);
> +	atomic64_set(&rx_ctx->resync_req, ((u64)ntohl(seq) << 32) | RESYNC_REQ);
> +}
> +
> +/* 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_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
> diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
> index 0f034c3..6281e2a 100644
> --- a/net/tls/tls_device.c
> +++ b/net/tls/tls_device.c
> @@ -676,6 +676,47 @@ static void tls_device_resync_rx(struct tls_context *tls_ctx,
>   	clear_bit_unlock(TLS_RX_SYNC_RUNNING, &tls_ctx->flags);
>   }
>   
> +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);
> @@ -718,6 +759,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);
>
diff mbox series

Patch

diff --git a/include/net/tls.h b/include/net/tls.h
index 697df45..e70dc8b 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -319,11 +319,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;
@@ -342,6 +350,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
@@ -631,13 +643,37 @@  static inline void *__tls_driver_ctx(struct tls_context *tls_ctx,
 }
 #endif
 
+#define RESYNC_REQ BIT(0)
+#define RESYNC_REQ_ASYNC BIT(1)
 /* The TLS context is valid until sk_destruct is called */
 static inline void tls_offload_rx_resync_request(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_req, ((u64)ntohl(seq) << 32) | 1);
+	atomic64_set(&rx_ctx->resync_req, ((u64)ntohl(seq) << 32) | RESYNC_REQ);
+}
+
+/* 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_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
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index 0f034c3..6281e2a 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -676,6 +676,47 @@  static void tls_device_resync_rx(struct tls_context *tls_ctx,
 	clear_bit_unlock(TLS_RX_SYNC_RUNNING, &tls_ctx->flags);
 }
 
+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);
@@ -718,6 +759,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);