Skip to content

Commit

Permalink
Merge branch 'nfp-tls-implement-the-stream-sync-RX-resync'
Browse files Browse the repository at this point in the history
Jakub Kicinski says:

====================
nfp: tls: implement the stream sync RX resync

This small series adds support for using the device
in stream scan RX resync mode which improves the RX
resync success rate. Without stream scan it's pretty
much impossible to successfully resync a continuous
stream.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 20, 2019
2 parents 8fb0d2c + 6a35ddc commit 5f04a6d
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 26 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/netronome/nfp/ccm.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum nfp_ccm_type {
NFP_CCM_TYPE_CRYPTO_ADD = 10,
NFP_CCM_TYPE_CRYPTO_DEL = 11,
NFP_CCM_TYPE_CRYPTO_UPDATE = 12,
NFP_CCM_TYPE_CRYPTO_RESYNC = 13,
__NFP_CCM_TYPE_MAX,
};

Expand Down
15 changes: 15 additions & 0 deletions drivers/net/ethernet/netronome/nfp/crypto/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#ifndef NFP_CRYPTO_H
#define NFP_CRYPTO_H 1

struct net_device;
struct nfp_net;
struct nfp_net_tls_resync_req;

struct nfp_net_tls_offload_ctx {
__be32 fw_handle[2];

Expand All @@ -17,11 +21,22 @@ struct nfp_net_tls_offload_ctx {

#ifdef CONFIG_TLS_DEVICE
int nfp_net_tls_init(struct nfp_net *nn);
int nfp_net_tls_rx_resync_req(struct net_device *netdev,
struct nfp_net_tls_resync_req *req,
void *pkt, unsigned int pkt_len);
#else
static inline int nfp_net_tls_init(struct nfp_net *nn)
{
return 0;
}

static inline int
nfp_net_tls_rx_resync_req(struct net_device *netdev,
struct nfp_net_tls_resync_req *req,
void *pkt, unsigned int pkt_len)
{
return -EOPNOTSUPP;
}
#endif

#endif
8 changes: 8 additions & 0 deletions drivers/net/ethernet/netronome/nfp/crypto/fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
#define NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC 0
#define NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC 1

struct nfp_net_tls_resync_req {
__be32 fw_handle[2];
__be32 tcp_seq;
u8 l3_offset;
u8 l4_offset;
u8 resv[2];
};

struct nfp_crypto_reply_simple {
struct nfp_ccm_hdr hdr;
__be32 error;
Expand Down
89 changes: 84 additions & 5 deletions drivers/net/ethernet/netronome/nfp/crypto/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <linux/ipv6.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <net/inet6_hashtables.h>
#include <net/tls.h>

#include "../ccm.h"
Expand Down Expand Up @@ -391,8 +392,9 @@ nfp_net_tls_add(struct net_device *netdev, struct sock *sk,
if (direction == TLS_OFFLOAD_CTX_DIR_TX)
return 0;

tls_offload_rx_resync_set_type(sk,
TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT);
if (!nn->tlv_caps.tls_resync_ss)
tls_offload_rx_resync_set_type(sk, TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT);

return 0;

err_fw_remove:
Expand Down Expand Up @@ -424,6 +426,7 @@ nfp_net_tls_resync(struct net_device *netdev, struct sock *sk, u32 seq,
struct nfp_net *nn = netdev_priv(netdev);
struct nfp_net_tls_offload_ctx *ntls;
struct nfp_crypto_req_update *req;
enum nfp_ccm_type type;
struct sk_buff *skb;
gfp_t flags;
int err;
Expand All @@ -442,15 +445,18 @@ nfp_net_tls_resync(struct net_device *netdev, struct sock *sk, u32 seq,
req->tcp_seq = cpu_to_be32(seq);
memcpy(req->rec_no, rcd_sn, sizeof(req->rec_no));

type = NFP_CCM_TYPE_CRYPTO_UPDATE;
if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
err = nfp_net_tls_communicate_simple(nn, skb, "sync",
NFP_CCM_TYPE_CRYPTO_UPDATE);
err = nfp_net_tls_communicate_simple(nn, skb, "sync", type);
if (err)
return err;
ntls->next_seq = seq;
} else {
nfp_ccm_mbox_post(nn, skb, NFP_CCM_TYPE_CRYPTO_UPDATE,
if (nn->tlv_caps.tls_resync_ss)
type = NFP_CCM_TYPE_CRYPTO_RESYNC;
nfp_ccm_mbox_post(nn, skb, type,
sizeof(struct nfp_crypto_reply_simple));
atomic_inc(&nn->ktls_rx_resync_sent);
}

return 0;
Expand All @@ -462,6 +468,79 @@ static const struct tlsdev_ops nfp_net_tls_ops = {
.tls_dev_resync = nfp_net_tls_resync,
};

int nfp_net_tls_rx_resync_req(struct net_device *netdev,
struct nfp_net_tls_resync_req *req,
void *pkt, unsigned int pkt_len)
{
struct nfp_net *nn = netdev_priv(netdev);
struct nfp_net_tls_offload_ctx *ntls;
struct ipv6hdr *ipv6h;
struct tcphdr *th;
struct iphdr *iph;
struct sock *sk;
__be32 tcp_seq;
int err;

iph = pkt + req->l3_offset;
ipv6h = pkt + req->l3_offset;
th = pkt + req->l4_offset;

if ((u8 *)&th[1] > (u8 *)pkt + pkt_len) {
netdev_warn_once(netdev, "invalid TLS RX resync request (l3_off: %hhu l4_off: %hhu pkt_len: %u)\n",
req->l3_offset, req->l4_offset, pkt_len);
err = -EINVAL;
goto err_cnt_ign;
}

switch (iph->version) {
case 4:
sk = inet_lookup_established(dev_net(netdev), &tcp_hashinfo,
iph->saddr, th->source, iph->daddr,
th->dest, netdev->ifindex);
break;
#if IS_ENABLED(CONFIG_IPV6)
case 6:
sk = __inet6_lookup_established(dev_net(netdev), &tcp_hashinfo,
&ipv6h->saddr, th->source,
&ipv6h->daddr, ntohs(th->dest),
netdev->ifindex, 0);
break;
#endif
default:
netdev_warn_once(netdev, "invalid TLS RX resync request (l3_off: %hhu l4_off: %hhu ipver: %u)\n",
req->l3_offset, req->l4_offset, iph->version);
err = -EINVAL;
goto err_cnt_ign;
}

err = 0;
if (!sk)
goto err_cnt_ign;
if (!tls_is_sk_rx_device_offloaded(sk) ||
sk->sk_shutdown & RCV_SHUTDOWN)
goto err_put_sock;

ntls = tls_driver_ctx(sk, TLS_OFFLOAD_CTX_DIR_RX);
/* some FW versions can't report the handle and report 0s */
if (memchr_inv(&req->fw_handle, 0, sizeof(req->fw_handle)) &&
memcmp(&req->fw_handle, &ntls->fw_handle, sizeof(ntls->fw_handle)))
goto err_put_sock;

/* copy to ensure alignment */
memcpy(&tcp_seq, &req->tcp_seq, sizeof(tcp_seq));
tls_offload_rx_resync_request(sk, tcp_seq);
atomic_inc(&nn->ktls_rx_resync_req);

sock_gen_put(sk);
return 0;

err_put_sock:
sock_gen_put(sk);
err_cnt_ign:
atomic_inc(&nn->ktls_rx_resync_ign);
return err;
}

static int nfp_net_tls_reset(struct nfp_net *nn)
{
struct nfp_crypto_req_reset *req;
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@ struct nfp_net_dp {
* @ktls_conn_id_gen: Trivial generator for kTLS connection ids (for TX)
* @ktls_no_space: Counter of firmware rejecting kTLS connection due to
* lack of space
* @ktls_rx_resync_req: Counter of TLS RX resync requested
* @ktls_rx_resync_ign: Counter of TLS RX resync requests ignored
* @ktls_rx_resync_sent: Counter of TLS RX resync completed
* @mbox_cmsg: Common Control Message via vNIC mailbox state
* @mbox_cmsg.queue: CCM mbox queue of pending messages
* @mbox_cmsg.wq: CCM mbox wait queue of waiting processes
Expand Down Expand Up @@ -674,6 +677,9 @@ struct nfp_net {
atomic64_t ktls_conn_id_gen;

atomic_t ktls_no_space;
atomic_t ktls_rx_resync_req;
atomic_t ktls_rx_resync_ign;
atomic_t ktls_rx_resync_sent;

struct {
struct sk_buff_head queue;
Expand Down
25 changes: 15 additions & 10 deletions drivers/net/ethernet/netronome/nfp/nfp_net_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "nfp_net_sriov.h"
#include "nfp_port.h"
#include "crypto/crypto.h"
#include "crypto/fw.h"

/**
* nfp_net_get_fw_version() - Read and parse the FW version
Expand Down Expand Up @@ -1661,9 +1662,9 @@ nfp_net_set_hash_desc(struct net_device *netdev, struct nfp_meta_parsed *meta,
&rx_hash->hash);
}

static void *
static bool
nfp_net_parse_meta(struct net_device *netdev, struct nfp_meta_parsed *meta,
void *data, int meta_len)
void *data, void *pkt, unsigned int pkt_len, int meta_len)
{
u32 meta_info;

Expand Down Expand Up @@ -1693,14 +1694,20 @@ nfp_net_parse_meta(struct net_device *netdev, struct nfp_meta_parsed *meta,
(__force __wsum)__get_unaligned_cpu32(data);
data += 4;
break;
case NFP_NET_META_RESYNC_INFO:
if (nfp_net_tls_rx_resync_req(netdev, data, pkt,
pkt_len))
return NULL;
data += sizeof(struct nfp_net_tls_resync_req);
break;
default:
return NULL;
return true;
}

meta_info >>= NFP_NET_META_FIELD_SIZE;
}

return data;
return data != pkt;
}

static void
Expand Down Expand Up @@ -1885,12 +1892,10 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
nfp_net_set_hash_desc(dp->netdev, &meta,
rxbuf->frag + meta_off, rxd);
} else if (meta_len) {
void *end;

end = nfp_net_parse_meta(dp->netdev, &meta,
rxbuf->frag + meta_off,
meta_len);
if (unlikely(end != rxbuf->frag + pkt_off)) {
if (unlikely(nfp_net_parse_meta(dp->netdev, &meta,
rxbuf->frag + meta_off,
rxbuf->frag + pkt_off,
pkt_len, meta_len))) {
nn_dp_warn(dp, "invalid RX packet metadata\n");
nfp_net_rx_drop(dp, r_vec, rx_ring, rxbuf,
NULL);
Expand Down
41 changes: 33 additions & 8 deletions drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,30 @@ static void nfp_net_tlv_caps_reset(struct nfp_net_tlv_caps *caps)
caps->mbox_len = NFP_NET_CFG_MBOX_VAL_MAX_SZ;
}

static bool
nfp_net_tls_parse_crypto_ops(struct device *dev, struct nfp_net_tlv_caps *caps,
u8 __iomem *ctrl_mem, u8 __iomem *data,
unsigned int length, unsigned int offset,
bool rx_stream_scan)
{
/* Ignore the legacy TLV if new one was already parsed */
if (caps->tls_resync_ss && !rx_stream_scan)
return true;

if (length < 32) {
dev_err(dev,
"CRYPTO OPS TLV should be at least 32B, is %dB offset:%u\n",
length, offset);
return false;
}

caps->crypto_ops = readl(data);
caps->crypto_enable_off = data - ctrl_mem + 16;
caps->tls_resync_ss = rx_stream_scan;

return true;
}

int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
struct nfp_net_tlv_caps *caps)
{
Expand Down Expand Up @@ -104,15 +128,10 @@ int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
caps->mbox_cmsg_types = readl(data);
break;
case NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS:
if (length < 32) {
dev_err(dev,
"CRYPTO OPS TLV should be at least 32B, is %dB offset:%u\n",
length, offset);
if (!nfp_net_tls_parse_crypto_ops(dev, caps, ctrl_mem,
data, length, offset,
false))
return -EINVAL;
}

caps->crypto_ops = readl(data);
caps->crypto_enable_off = data - ctrl_mem + 16;
break;
case NFP_NET_CFG_TLV_TYPE_VNIC_STATS:
if ((data - ctrl_mem) % 8) {
Expand All @@ -123,6 +142,12 @@ int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
caps->vnic_stats_off = data - ctrl_mem;
caps->vnic_stats_cnt = length / 10;
break;
case NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN:
if (!nfp_net_tls_parse_crypto_ops(dev, caps, ctrl_mem,
data, length, offset,
true))
return -EINVAL;
break;
default:
if (!FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr))
break;
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#define NFP_NET_META_PORTID 5
#define NFP_NET_META_CSUM 6 /* checksum complete type */
#define NFP_NET_META_CONN_HANDLE 7
#define NFP_NET_META_RESYNC_INFO 8 /* RX resync info request */

#define NFP_META_PORT_ID_CTRL ~0U

Expand Down Expand Up @@ -479,6 +480,7 @@
* 8 words, bitmaps of supported and enabled crypto operations.
* First 16B (4 words) contains a bitmap of supported crypto operations,
* and next 16B contain the enabled operations.
* This capability is made obsolete by ones with better sync methods.
*
* %NFP_NET_CFG_TLV_TYPE_VNIC_STATS:
* Variable, per-vNIC statistics, data should be 8B aligned (FW should insert
Expand All @@ -490,6 +492,10 @@
* This TLV overwrites %NFP_NET_CFG_STATS_* values (statistics in this TLV
* duplicate the old ones, so driver should be careful not to unnecessarily
* render both).
*
* %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN:
* Same as %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS, but crypto TLS does stream scan
* RX sync, rather than kernel-assisted sync.
*/
#define NFP_NET_CFG_TLV_TYPE_UNKNOWN 0
#define NFP_NET_CFG_TLV_TYPE_RESERVED 1
Expand All @@ -502,6 +508,7 @@
#define NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES 10
#define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS 11 /* see crypto/fw.h */
#define NFP_NET_CFG_TLV_TYPE_VNIC_STATS 12
#define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN 13

struct device;

Expand All @@ -516,6 +523,7 @@ struct device;
* @crypto_enable_off: offset of crypto ops enable region
* @vnic_stats_off: offset of vNIC stats area
* @vnic_stats_cnt: number of vNIC stats
* @tls_resync_ss: TLS resync will be performed via stream scan
*/
struct nfp_net_tlv_caps {
u32 me_freq_mhz;
Expand All @@ -527,6 +535,7 @@ struct nfp_net_tlv_caps {
unsigned int crypto_enable_off;
unsigned int vnic_stats_off;
unsigned int vnic_stats_cnt;
unsigned int tls_resync_ss:1;
};

int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
Expand Down
Loading

0 comments on commit 5f04a6d

Please sign in to comment.