diff options
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/crypto/crypto.h | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/nfp_net.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 56 |
3 files changed, 65 insertions, 0 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/crypto/crypto.h b/drivers/net/ethernet/netronome/nfp/crypto/crypto.h index 43aed51a8769..1f97fb443134 100644 --- a/drivers/net/ethernet/netronome/nfp/crypto/crypto.h +++ b/drivers/net/ethernet/netronome/nfp/crypto/crypto.h @@ -4,6 +4,13 @@ #ifndef NFP_CRYPTO_H #define NFP_CRYPTO_H 1 +struct nfp_net_tls_offload_ctx { + __be32 fw_handle[2]; + + u32 next_seq; + bool out_of_sync; +}; + #ifdef CONFIG_TLS_DEVICE int nfp_net_tls_init(struct nfp_net *nn); #else diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index 7010c9f1e676..689e9e1938c8 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -459,6 +459,7 @@ struct nfp_stat_pair { * @netdev: Backpointer to net_device structure * @is_vf: Is the driver attached to a VF? * @chained_metadata_format: Firemware will use new metadata format + * @ktls_tx: Is kTLS TX enabled? * @rx_dma_dir: Mapping direction for RX buffers * @rx_dma_off: Offset at which DMA packets (for XDP headroom) * @rx_offset: Offset in the RX buffers where packet data starts @@ -483,6 +484,7 @@ struct nfp_net_dp { u8 is_vf:1; u8 chained_metadata_format:1; + u8 ktls_tx:1; u8 rx_dma_dir; u8 rx_offset; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index df21effec320..52f20f191eed 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -36,6 +36,7 @@ #include <linux/vmalloc.h> #include <linux/ktime.h> +#include <net/tls.h> #include <net/vxlan.h> #include "nfpcore/nfp_nsp.h" @@ -801,6 +802,55 @@ static void nfp_net_tx_csum(struct nfp_net_dp *dp, u64_stats_update_end(&r_vec->tx_sync); } +#ifdef CONFIG_TLS_DEVICE +static struct sk_buff * +nfp_net_tls_tx(struct nfp_net_dp *dp, struct sk_buff *skb, u64 *tls_handle, + int *nr_frags) +{ + struct nfp_net_tls_offload_ctx *ntls; + struct sk_buff *nskb; + u32 datalen, seq; + + if (likely(!dp->ktls_tx)) + return skb; + if (!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk)) + return skb; + + datalen = skb->len - (skb_transport_offset(skb) + tcp_hdrlen(skb)); + seq = ntohl(tcp_hdr(skb)->seq); + ntls = tls_driver_ctx(skb->sk, TLS_OFFLOAD_CTX_DIR_TX); + if (unlikely(ntls->next_seq != seq || ntls->out_of_sync)) { + /* Pure ACK out of order already */ + if (!datalen) + return skb; + + nskb = tls_encrypt_skb(skb); + if (!nskb) + return NULL; + /* encryption wasn't necessary */ + if (nskb == skb) + return skb; + /* we don't re-check ring space */ + if (unlikely(skb_is_nonlinear(nskb))) { + nn_dp_warn(dp, "tls_encrypt_skb() produced fragmented frame\n"); + dev_kfree_skb_any(nskb); + return NULL; + } + + /* jump forward, a TX may have gotten lost, need to sync TX */ + if (!ntls->out_of_sync && seq - ntls->next_seq < U32_MAX / 4) + ntls->out_of_sync = true; + + *nr_frags = 0; + return nskb; + } + + memcpy(tls_handle, ntls->fw_handle, sizeof(ntls->fw_handle)); + ntls->next_seq += datalen; + return skb; +} +#endif + static void nfp_net_tx_xmit_more_flush(struct nfp_net_tx_ring *tx_ring) { wmb(); @@ -893,6 +943,12 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_BUSY; } +#ifdef CONFIG_TLS_DEVICE + skb = nfp_net_tls_tx(dp, skb, &tls_handle, &nr_frags); + if (unlikely(!skb)) + goto err_flush; +#endif + md_bytes = nfp_net_prep_tx_meta(skb, tls_handle); if (unlikely(md_bytes < 0)) goto err_flush; |