Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b20ac8da authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-tls-small-general-improvements'



Jakub Kicinski says:

====================
net/tls: small general improvements

This series cleans up and improves the tls code, mostly the offload
parts.

First a slight performance optimization - avoiding unnecessary re-
-encryption of records in patch 1.  Next patch 2 makes the code
more resilient by checking for errors in skb_copy_bits().  Next
commit removes a warning which can be triggered in normal operation,
(especially for devices explicitly making use of the fallback path).
Next two paths change the condition checking around the call to
tls_device_decrypted() to make it easier to extend.  Remaining
commits are centered around reorganizing struct tls_context for
better cache utilization.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7e7d199e fb0f886f
Loading
Loading
Loading
Loading
+0 −19
Original line number Diff line number Diff line
@@ -379,7 +379,6 @@ by the driver:
   but did not arrive in the expected order
 * ``tx_tls_drop_no_sync_data`` - number of TX packets dropped because
   they arrived out of order and associated record could not be found
   (see also :ref:`pre_tls_data`)

Notable corner cases, exceptions and additional requirements
============================================================
@@ -462,21 +461,3 @@ Redirects leak clear text

In the RX direction, if segment has already been decrypted by the device
and it gets redirected or mirrored - clear text will be transmitted out.

.. _pre_tls_data:

Transmission of pre-TLS data
----------------------------

User can enqueue some already encrypted and framed records before enabling
``ktls`` on the socket. Those records have to get sent as they are. This is
perfectly easy to handle in the software case - such data will be waiting
in the TCP layer, TLS ULP won't see it. In the offloaded case when pre-queued
segment reaches transmission point it appears to be out of order (before the
expected TCP sequence number) and the stack does not have a record information
associated.

All segments without record information cannot, however, be assumed to be
pre-queued data, because a race condition exists between TCP stack queuing
a retransmission, the driver seeing the retransmission and TCP ACK arriving
for the retransmitted data.
+1 −0
Original line number Diff line number Diff line
@@ -1063,6 +1063,7 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
				     int max_page_order,
				     int *errcode,
				     gfp_t gfp_mask);
struct sk_buff *alloc_skb_for_msg(struct sk_buff *first);

/* Layout of fast clones : [skb1][skb2][fclone_ref] */
struct sk_buff_fclones {
+18 −18
Original line number Diff line number Diff line
@@ -236,34 +236,32 @@ struct tls_prot_info {
};

struct tls_context {
	/* read-only cache line */
	struct tls_prot_info prot_info;

	union tls_crypto_context crypto_send;
	union tls_crypto_context crypto_recv;
	u8 tx_conf:3;
	u8 rx_conf:3;

	struct list_head list;
	struct net_device *netdev;
	refcount_t refcount;
	int (*push_pending_record)(struct sock *sk, int flags);
	void (*sk_write_space)(struct sock *sk);

	void *priv_ctx_tx;
	void *priv_ctx_rx;

	u8 tx_conf:3;
	u8 rx_conf:3;
	struct net_device *netdev;

	/* rw cache line */
	struct cipher_context tx;
	struct cipher_context rx;

	struct scatterlist *partially_sent_record;
	u16 partially_sent_offset;

	unsigned long flags;
	bool in_tcp_sendpages;
	bool pending_open_record_frags;
	unsigned long flags;

	int (*push_pending_record)(struct sock *sk, int flags);

	void (*sk_write_space)(struct sock *sk);
	/* cache cold stuff */
	void (*sk_destruct)(struct sock *sk);
	void (*sk_proto_close)(struct sock *sk, long timeout);

@@ -275,6 +273,12 @@ struct tls_context {
			   int __user *optlen);
	int  (*hash)(struct sock *sk);
	void (*unhash)(struct sock *sk);

	union tls_crypto_context crypto_send;
	union tls_crypto_context crypto_recv;

	struct list_head list;
	refcount_t refcount;
};

enum tls_offload_ctx_dir {
@@ -442,20 +446,16 @@ static inline struct tls_context *tls_get_ctx(const struct sock *sk)
}

static inline void tls_advance_record_sn(struct sock *sk,
					 struct cipher_context *ctx,
					 int version)
					 struct tls_prot_info *prot,
					 struct cipher_context *ctx)
{
	struct tls_context *tls_ctx = tls_get_ctx(sk);
	struct tls_prot_info *prot = &tls_ctx->prot_info;

	if (tls_bigint_increment(ctx->rec_seq, prot->rec_seq_size))
		tls_err_abort(sk, EBADMSG);

	if (version != TLS_1_3_VERSION) {
	if (prot->version != TLS_1_3_VERSION)
		tls_bigint_increment(ctx->iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
				     prot->iv_size);
}
}

static inline void tls_fill_prepend(struct tls_context *ctx,
			     char *buf,
+25 −0
Original line number Diff line number Diff line
@@ -913,6 +913,31 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
#undef C
}

/**
 * alloc_skb_for_msg() - allocate sk_buff to wrap frag list forming a msg
 * @first: first sk_buff of the msg
 */
struct sk_buff *alloc_skb_for_msg(struct sk_buff *first)
{
	struct sk_buff *n;

	n = alloc_skb(0, GFP_ATOMIC);
	if (!n)
		return NULL;

	n->len = first->len;
	n->data_len = first->len;
	n->truesize = first->truesize;

	skb_shinfo(n)->frag_list = first;

	__copy_skb_header(n, first);
	n->destructor = NULL;

	return n;
}
EXPORT_SYMBOL_GPL(alloc_skb_for_msg);

/**
 *	skb_morph	-	morph one skb into another
 *	@dst: the skb to receive the contents
+2 −6
Original line number Diff line number Diff line
@@ -160,18 +160,14 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
					return 0;
				}

				skb = alloc_skb(0, GFP_ATOMIC);
				skb = alloc_skb_for_msg(head);
				if (!skb) {
					STRP_STATS_INCR(strp->stats.mem_fail);
					desc->error = -ENOMEM;
					return 0;
				}
				skb->len = head->len;
				skb->data_len = head->len;
				skb->truesize = head->truesize;
				*_strp_msg(skb) = *_strp_msg(head);

				strp->skb_nextp = &head->next;
				skb_shinfo(skb)->frag_list = head;
				strp->skb_head = skb;
				head = skb;
			} else {
Loading