Skip to content

Commit

Permalink
Merge branch 'net-tls-add-ctrl-path-tracing-and-statistics'
Browse files Browse the repository at this point in the history
Jakub Kicinski says:

====================
net/tls: add ctrl path tracing and statistics

This set adds trace events related to TLS offload and basic MIB stats
for TLS.

First patch contains the TLS offload related trace points. Those are
helpful in troubleshooting offload issues, especially around the
resync paths.

Second patch adds a tracepoint to the fastpath of device offload,
it's separated out in case there will be objections to adding
fast path tracepoints. Again, it's quite useful for debugging
offload issues.

Next four patches add MIB statistics. The statistics are implemented
as per-cpu per-netns counters. Since there are currently no fast path
statistics we could move to atomic variables. Per-CPU seem more common.

Most basic statistics are number of created and live sessions, broken
out to offloaded and non-offloaded. Users seem to like those a lot.

Next there is a statistic for decryption errors. These are primarily
useful for device offload debug, in normal deployments decryption
errors should not be common.

Last but not least a counter for device RX resync.
====================

Reviewed-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 5, 2019
2 parents 6f4c930 + a4d26fd commit 128d23c
Show file tree
Hide file tree
Showing 13 changed files with 425 additions and 15 deletions.
26 changes: 26 additions & 0 deletions Documentation/networking/tls.rst
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,29 @@ A patchset to OpenSSL to use ktls as the record layer is
of calling send directly after a handshake using gnutls.
Since it doesn't implement a full record layer, control
messages are not supported.

Statistics
==========

TLS implementation exposes the following per-namespace statistics
(``/proc/net/tls_stat``):

- ``TlsCurrTxSw``, ``TlsCurrRxSw`` -
number of TX and RX sessions currently installed where host handles
cryptography

- ``TlsCurrTxDevice``, ``TlsCurrRxDevice`` -
number of TX and RX sessions currently installed where NIC handles
cryptography

- ``TlsTxSw``, ``TlsRxSw`` -
number of TX and RX sessions opened with host cryptography

- ``TlsTxDevice``, ``TlsRxDevice`` -
number of TX and RX sessions opened with NIC cryptography

- ``TlsDecryptError`` -
record decryption failed (e.g. due to incorrect authentication tag)

- ``TlsDeviceRxResync`` -
number of RX resyncs sent to NICs handling cryptography
3 changes: 2 additions & 1 deletion drivers/net/ethernet/netronome/nfp/nfp_net_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,8 @@ nfp_net_tls_tx(struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec,

/* jump forward, a TX may have gotten lost, need to sync TX */
if (!resync_pending && seq - ntls->next_seq < U32_MAX / 4)
tls_offload_tx_resync_request(nskb->sk);
tls_offload_tx_resync_request(nskb->sk, seq,
ntls->next_seq);

*nr_frags = 0;
return nskb;
Expand Down
3 changes: 3 additions & 0 deletions include/net/netns/mib.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ struct netns_mib {
#ifdef CONFIG_XFRM_STATISTICS
DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics);
#endif
#if IS_ENABLED(CONFIG_TLS)
DEFINE_SNMP_STAT(struct linux_tls_mib, tls_statistics);
#endif
};

#endif
6 changes: 6 additions & 0 deletions include/net/snmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ struct linux_xfrm_mib {
unsigned long mibs[LINUX_MIB_XFRMMAX];
};

/* Linux TLS */
#define LINUX_MIB_TLSMAX __LINUX_MIB_TLSMAX
struct linux_tls_mib {
unsigned long mibs[LINUX_MIB_TLSMAX];
};

#define DEFINE_SNMP_STAT(type, name) \
__typeof__(type) __percpu *name
#define DEFINE_SNMP_STAT_ATOMIC(type, name) \
Expand Down
21 changes: 14 additions & 7 deletions include/net/tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <linux/netdevice.h>
#include <linux/rcupdate.h>

#include <net/net_namespace.h>
#include <net/tcp.h>
#include <net/strparser.h>
#include <crypto/aead.h>
Expand Down Expand Up @@ -73,6 +74,15 @@
*/
#define TLS_AES_CCM_IV_B0_BYTE 2

#define __TLS_INC_STATS(net, field) \
__SNMP_INC_STATS((net)->mib.tls_statistics, field)
#define TLS_INC_STATS(net, field) \
SNMP_INC_STATS((net)->mib.tls_statistics, field)
#define __TLS_DEC_STATS(net, field) \
__SNMP_DEC_STATS((net)->mib.tls_statistics, field)
#define TLS_DEC_STATS(net, field) \
SNMP_DEC_STATS((net)->mib.tls_statistics, field)

enum {
TLS_BASE,
TLS_SW,
Expand Down Expand Up @@ -594,13 +604,6 @@ tls_offload_rx_resync_set_type(struct sock *sk, enum tls_offload_sync_type type)
tls_offload_ctx_rx(tls_ctx)->resync_type = type;
}

static inline void tls_offload_tx_resync_request(struct sock *sk)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);

WARN_ON(test_and_set_bit(TLS_TX_SYNC_SCHED, &tls_ctx->flags));
}

/* Driver's seq tracking has to be disabled until resync succeeded */
static inline bool tls_offload_tx_resync_pending(struct sock *sk)
{
Expand All @@ -612,6 +615,9 @@ static inline bool tls_offload_tx_resync_pending(struct sock *sk)
return ret;
}

int __net_init tls_proc_init(struct net *net);
void __net_exit tls_proc_fini(struct net *net);

int tls_proccess_cmsg(struct sock *sk, struct msghdr *msg,
unsigned char *record_type);
int decrypt_skb(struct sock *sk, struct sk_buff *skb,
Expand All @@ -634,6 +640,7 @@ void tls_device_free_resources_tx(struct sock *sk);
int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx);
void tls_device_offload_cleanup_rx(struct sock *sk);
void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq);
void tls_offload_tx_resync_request(struct sock *sk, u32 got_seq, u32 exp_seq);
int tls_device_decrypted(struct sock *sk, struct sk_buff *skb);
#else
static inline void tls_device_init(void) {}
Expand Down
17 changes: 17 additions & 0 deletions include/uapi/linux/snmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,4 +323,21 @@ enum
__LINUX_MIB_XFRMMAX
};

/* linux TLS mib definitions */
enum
{
LINUX_MIB_TLSNUM = 0,
LINUX_MIB_TLSCURRTXSW, /* TlsCurrTxSw */
LINUX_MIB_TLSCURRRXSW, /* TlsCurrRxSw */
LINUX_MIB_TLSCURRTXDEVICE, /* TlsCurrTxDevice */
LINUX_MIB_TLSCURRRXDEVICE, /* TlsCurrRxDevice */
LINUX_MIB_TLSTXSW, /* TlsTxSw */
LINUX_MIB_TLSRXSW, /* TlsRxSw */
LINUX_MIB_TLSTXDEVICE, /* TlsTxDevice */
LINUX_MIB_TLSRXDEVICE, /* TlsRxDevice */
LINUX_MIB_TLSDECRYPTERROR, /* TlsDecryptError */
LINUX_MIB_TLSRXDEVICERESYNC, /* TlsRxDeviceResync */
__LINUX_MIB_TLSMAX
};

#endif /* _LINUX_SNMP_H */
4 changes: 3 additions & 1 deletion net/tls/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
# Makefile for the TLS subsystem.
#

CFLAGS_trace.o := -I$(src)

obj-$(CONFIG_TLS) += tls.o

tls-y := tls_main.o tls_sw.o
tls-y := tls_main.o tls_sw.o tls_proc.o trace.o

tls-$(CONFIG_TLS_TOE) += tls_toe.o
tls-$(CONFIG_TLS_DEVICE) += tls_device.o tls_device_fallback.o
36 changes: 34 additions & 2 deletions net/tls/tls_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include <net/tcp.h>
#include <net/tls.h>

#include "trace.h"

/* device_offload_lock is used to synchronize tls_dev_add
* against NETDEV_DOWN notifications.
*/
Expand Down Expand Up @@ -202,6 +204,15 @@ void tls_device_free_resources_tx(struct sock *sk)
tls_free_partial_record(sk, tls_ctx);
}

void tls_offload_tx_resync_request(struct sock *sk, u32 got_seq, u32 exp_seq)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);

trace_tls_device_tx_resync_req(sk, got_seq, exp_seq);
WARN_ON(test_and_set_bit(TLS_TX_SYNC_SCHED, &tls_ctx->flags));
}
EXPORT_SYMBOL_GPL(tls_offload_tx_resync_request);

static void tls_device_resync_tx(struct sock *sk, struct tls_context *tls_ctx,
u32 seq)
{
Expand All @@ -216,6 +227,7 @@ static void tls_device_resync_tx(struct sock *sk, struct tls_context *tls_ctx,

rcd_sn = tls_ctx->tx.rec_seq;

trace_tls_device_tx_resync_send(sk, seq, rcd_sn);
down_read(&device_offload_lock);
netdev = tls_ctx->netdev;
if (netdev)
Expand Down Expand Up @@ -637,24 +649,28 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
static void tls_device_resync_rx(struct tls_context *tls_ctx,
struct sock *sk, u32 seq, u8 *rcd_sn)
{
struct tls_offload_context_rx *rx_ctx = tls_offload_ctx_rx(tls_ctx);
struct net_device *netdev;

if (WARN_ON(test_and_set_bit(TLS_RX_SYNC_RUNNING, &tls_ctx->flags)))
return;

trace_tls_device_rx_resync_send(sk, seq, rcd_sn, rx_ctx->resync_type);
netdev = READ_ONCE(tls_ctx->netdev);
if (netdev)
netdev->tlsdev_ops->tls_dev_resync(netdev, sk, seq, rcd_sn,
TLS_OFFLOAD_CTX_DIR_RX);
clear_bit_unlock(TLS_RX_SYNC_RUNNING, &tls_ctx->flags);
TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXDEVICERESYNC);
}

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;
u8 rcd_sn[TLS_MAX_REC_SEQ_SIZE];
u32 sock_data, is_req_pending;
struct tls_prot_info *prot;
u32 is_req_pending;
s64 resync_req;
u32 req_seq;

Expand Down Expand Up @@ -683,8 +699,12 @@ void tls_device_rx_resync_new_rec(struct sock *sk, u32 rcd_len, u32 seq)
/* head of next rec is already in, note that the sock_inq will
* include the currently parsed message when called from parser
*/
if (tcp_inq(sk) > rcd_len)
sock_data = tcp_inq(sk);
if (sock_data > rcd_len) {
trace_tls_device_rx_resync_nh_delay(sk, sock_data,
rcd_len);
return;
}

rx_ctx->resync_nh_do_now = 0;
seq += rcd_len;
Expand Down Expand Up @@ -728,6 +748,7 @@ static void tls_device_core_ctrl_rx_resync(struct tls_context *tls_ctx,

/* head of next rec is already in, parser will sync for us */
if (tcp_inq(sk) > rxm->full_len) {
trace_tls_device_rx_resync_nh_schedule(sk);
ctx->resync_nh_do_now = 1;
} else {
struct tls_prot_info *prot = &tls_ctx->prot_info;
Expand Down Expand Up @@ -830,6 +851,7 @@ int tls_device_decrypted(struct sock *sk, struct sk_buff *skb)
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_offload_context_rx *ctx = tls_offload_ctx_rx(tls_ctx);
struct strp_msg *rxm = strp_msg(skb);
int is_decrypted = skb->decrypted;
int is_encrypted = !is_decrypted;
struct sk_buff *skb_iter;
Expand All @@ -840,6 +862,10 @@ int tls_device_decrypted(struct sock *sk, struct sk_buff *skb)
is_encrypted &= !skb_iter->decrypted;
}

trace_tls_device_decrypted(sk, tcp_sk(sk)->copied_seq - rxm->full_len,
tls_ctx->rx.rec_seq, rxm->full_len,
is_encrypted, is_decrypted);

ctx->sw.decrypted |= is_decrypted;

/* Return immediately if the record is either entirely plaintext or
Expand Down Expand Up @@ -1013,6 +1039,8 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
rc = netdev->tlsdev_ops->tls_dev_add(netdev, sk, TLS_OFFLOAD_CTX_DIR_TX,
&ctx->crypto_send.info,
tcp_sk(sk)->write_seq);
trace_tls_device_offload_set(sk, TLS_OFFLOAD_CTX_DIR_TX,
tcp_sk(sk)->write_seq, rec_seq, rc);
if (rc)
goto release_lock;

Expand Down Expand Up @@ -1049,6 +1077,7 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)

int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx)
{
struct tls12_crypto_info_aes_gcm_128 *info;
struct tls_offload_context_rx *context;
struct net_device *netdev;
int rc = 0;
Expand Down Expand Up @@ -1096,6 +1125,9 @@ int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx)
rc = netdev->tlsdev_ops->tls_dev_add(netdev, sk, TLS_OFFLOAD_CTX_DIR_RX,
&ctx->crypto_recv.info,
tcp_sk(sk)->copied_seq);
info = (void *)&ctx->crypto_recv.info;
trace_tls_device_offload_set(sk, TLS_OFFLOAD_CTX_DIR_RX,
tcp_sk(sk)->copied_seq, info->rec_seq, rc);
if (rc)
goto free_sw_resources;

Expand Down
Loading

0 comments on commit 128d23c

Please sign in to comment.