Skip to content

Commit fd18d5f

Browse files
committed
Merge branch 'tls-rx-avoid-skb_cow_data'
Jakub Kicinski says: ==================== tls: rx: avoid skb_cow_data() TLS calls skb_cow_data() on the skb it received from strparser whenever it needs to hold onto the skb with the decrypted data. (The alternative being decrypting directly to a user space buffer in whic case the input skb doesn't get modified or used after.) TLS needs the decrypted skb: - almost always with TLS 1.3 (unless the new NoPad is enabled); - when user space buffer is too small to fit the record; - when BPF sockmap is enabled. Most of the time the skb we get out of strparser is a clone of a 64kB data unit coalsced by GRO. To make things worse skb_cow_data() tries to output a linear skb and allocates it with GFP_ATOMIC. This occasionally fails even under moderate memory pressure. This patch set rejigs the TLS Rx so that we don't expect decryption in place. The decryption handlers return an skb which may or may not be the skb from strparser. For TLS 1.3 this results in a 20-30% performance improvement without NoPad enabled. v2: rebase after 3d8c51b ("net/tls: Check for errors in tls_device_init") ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 3898f52 + fd31f39 commit fd18d5f

File tree

7 files changed

+333
-194
lines changed

7 files changed

+333
-194
lines changed

include/net/strparser.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ struct sk_skb_cb {
7272
/* strp users' data follows */
7373
struct tls_msg {
7474
u8 control;
75-
u8 decrypted;
7675
} tls;
7776
/* temp_reg is a temporary register used for bpf_convert_data_end_access
7877
* when dst_reg == src_reg.

include/net/tls.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,15 @@ struct tls_sw_context_rx {
116116
void (*saved_data_ready)(struct sock *sk);
117117

118118
struct sk_buff *recv_pkt;
119+
u8 reader_present;
119120
u8 async_capable:1;
120121
u8 zc_capable:1;
122+
u8 reader_contended:1;
121123
atomic_t decrypt_pending;
122124
/* protect crypto_wait with decrypt_pending*/
123125
spinlock_t decrypt_compl_lock;
126+
struct sk_buff_head async_hold;
127+
struct wait_queue_head wq;
124128
};
125129

126130
struct tls_record_info {

net/tls/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ CFLAGS_trace.o := -I$(src)
77

88
obj-$(CONFIG_TLS) += tls.o
99

10-
tls-y := tls_main.o tls_sw.o tls_proc.o trace.o
10+
tls-y := tls_main.o tls_sw.o tls_proc.o trace.o tls_strp.o
1111

1212
tls-$(CONFIG_TLS_TOE) += tls_toe.o
1313
tls-$(CONFIG_TLS_DEVICE) += tls_device.o tls_device_fallback.o

net/tls/tls.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
#include <linux/skmsg.h>
4040
#include <net/tls.h>
4141

42+
#define TLS_PAGE_ORDER (min_t(unsigned int, PAGE_ALLOC_COSTLY_ORDER, \
43+
TLS_MAX_PAYLOAD_SIZE >> PAGE_SHIFT))
44+
4245
#define __TLS_INC_STATS(net, field) \
4346
__SNMP_INC_STATS((net)->mib.tls_statistics, field)
4447
#define TLS_INC_STATS(net, field) \
@@ -118,20 +121,27 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx);
118121

119122
int tls_process_cmsg(struct sock *sk, struct msghdr *msg,
120123
unsigned char *record_type);
121-
int decrypt_skb(struct sock *sk, struct sk_buff *skb,
122-
struct scatterlist *sgout);
124+
int decrypt_skb(struct sock *sk, struct scatterlist *sgout);
123125

124126
int tls_sw_fallback_init(struct sock *sk,
125127
struct tls_offload_context_tx *offload_ctx,
126128
struct tls_crypto_info *crypto_info);
127129

130+
int tls_strp_msg_hold(struct sock *sk, struct sk_buff *skb,
131+
struct sk_buff_head *dst);
132+
128133
static inline struct tls_msg *tls_msg(struct sk_buff *skb)
129134
{
130135
struct sk_skb_cb *scb = (struct sk_skb_cb *)skb->cb;
131136

132137
return &scb->tls;
133138
}
134139

140+
static inline struct sk_buff *tls_strp_msg(struct tls_sw_context_rx *ctx)
141+
{
142+
return ctx->recv_pkt;
143+
}
144+
135145
#ifdef CONFIG_TLS_DEVICE
136146
int tls_device_init(void);
137147
void tls_device_cleanup(void);
@@ -140,8 +150,7 @@ void tls_device_free_resources_tx(struct sock *sk);
140150
int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx);
141151
void tls_device_offload_cleanup_rx(struct sock *sk);
142152
void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq);
143-
int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx,
144-
struct sk_buff *skb, struct strp_msg *rxm);
153+
int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx);
145154
#else
146155
static inline int tls_device_init(void) { return 0; }
147156
static inline void tls_device_cleanup(void) {}
@@ -165,8 +174,7 @@ static inline void
165174
tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq) {}
166175

167176
static inline int
168-
tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx,
169-
struct sk_buff *skb, struct strp_msg *rxm)
177+
tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx)
170178
{
171179
return 0;
172180
}

net/tls/tls_device.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -889,14 +889,19 @@ static void tls_device_core_ctrl_rx_resync(struct tls_context *tls_ctx,
889889
}
890890
}
891891

892-
static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb)
892+
static int
893+
tls_device_reencrypt(struct sock *sk, struct tls_sw_context_rx *sw_ctx)
893894
{
894-
struct strp_msg *rxm = strp_msg(skb);
895-
int err = 0, offset = rxm->offset, copy, nsg, data_len, pos;
896-
struct sk_buff *skb_iter, *unused;
895+
int err = 0, offset, copy, nsg, data_len, pos;
896+
struct sk_buff *skb, *skb_iter, *unused;
897897
struct scatterlist sg[1];
898+
struct strp_msg *rxm;
898899
char *orig_buf, *buf;
899900

901+
skb = tls_strp_msg(sw_ctx);
902+
rxm = strp_msg(skb);
903+
offset = rxm->offset;
904+
900905
orig_buf = kmalloc(rxm->full_len + TLS_HEADER_SIZE +
901906
TLS_CIPHER_AES_GCM_128_IV_SIZE, sk->sk_allocation);
902907
if (!orig_buf)
@@ -919,7 +924,7 @@ static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb)
919924
goto free_buf;
920925

921926
/* We are interested only in the decrypted data not the auth */
922-
err = decrypt_skb(sk, skb, sg);
927+
err = decrypt_skb(sk, sg);
923928
if (err != -EBADMSG)
924929
goto free_buf;
925930
else
@@ -974,10 +979,12 @@ static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb)
974979
return err;
975980
}
976981

977-
int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx,
978-
struct sk_buff *skb, struct strp_msg *rxm)
982+
int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx)
979983
{
980984
struct tls_offload_context_rx *ctx = tls_offload_ctx_rx(tls_ctx);
985+
struct tls_sw_context_rx *sw_ctx = tls_sw_ctx_rx(tls_ctx);
986+
struct sk_buff *skb = tls_strp_msg(sw_ctx);
987+
struct strp_msg *rxm = strp_msg(skb);
981988
int is_decrypted = skb->decrypted;
982989
int is_encrypted = !is_decrypted;
983990
struct sk_buff *skb_iter;
@@ -1000,7 +1007,7 @@ int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx,
10001007
* likely have initial fragments decrypted, and final ones not
10011008
* decrypted. We need to reencrypt that single SKB.
10021009
*/
1003-
return tls_device_reencrypt(sk, skb);
1010+
return tls_device_reencrypt(sk, sw_ctx);
10041011
}
10051012

10061013
/* Return immediately if the record is either entirely plaintext or
@@ -1017,7 +1024,7 @@ int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx,
10171024
}
10181025

10191026
ctx->resync_nh_reset = 1;
1020-
return tls_device_reencrypt(sk, skb);
1027+
return tls_device_reencrypt(sk, sw_ctx);
10211028
}
10221029

10231030
static void tls_device_attach(struct tls_context *ctx, struct sock *sk,

net/tls/tls_strp.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
#include <linux/skbuff.h>
4+
5+
#include "tls.h"
6+
7+
int tls_strp_msg_hold(struct sock *sk, struct sk_buff *skb,
8+
struct sk_buff_head *dst)
9+
{
10+
struct sk_buff *clone;
11+
12+
clone = skb_clone(skb, sk->sk_allocation);
13+
if (!clone)
14+
return -ENOMEM;
15+
__skb_queue_tail(dst, clone);
16+
return 0;
17+
}

0 commit comments

Comments
 (0)