From 58002ff3d5751c6da9e5cbcc4df3bc384d451f14 Mon Sep 17 00:00:00 2001 From: Tejasree Kondoj Date: Tue, 4 Feb 2020 16:47:15 +0530 Subject: [PATCH] net/octeontx2: add security in configure Adding security in eth device configure. Signed-off-by: Ankur Dwivedi Signed-off-by: Anoob Joseph Signed-off-by: Archana Muniganti Signed-off-by: Tejasree Kondoj Signed-off-by: Vamsi Attunuru Acked-by: Akhil Goyal --- doc/guides/nics/octeontx2.rst | 20 ++++ doc/guides/rel_notes/release_20_02.rst | 9 ++ drivers/crypto/octeontx2/otx2_ipsec_fp.h | 55 +++++++++ drivers/net/octeontx2/Makefile | 3 + drivers/net/octeontx2/meson.build | 5 +- drivers/net/octeontx2/otx2_ethdev.c | 17 ++- drivers/net/octeontx2/otx2_ethdev.h | 2 + drivers/net/octeontx2/otx2_ethdev_devargs.c | 19 +++ drivers/net/octeontx2/otx2_ethdev_sec.c | 122 ++++++++++++++++++++ drivers/net/octeontx2/otx2_ethdev_sec.h | 4 + 10 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 drivers/crypto/octeontx2/otx2_ipsec_fp.h diff --git a/doc/guides/nics/octeontx2.rst b/doc/guides/nics/octeontx2.rst index 2ff1dbda0e..60187ec72f 100644 --- a/doc/guides/nics/octeontx2.rst +++ b/doc/guides/nics/octeontx2.rst @@ -38,6 +38,7 @@ Features of the OCTEON TX2 Ethdev PMD are: - IEEE1588 timestamping - HW offloaded `ethdev Rx queue` to `eventdev event queue` packet injection - Support Rx interrupt +- Inline IPsec processing support Prerequisites ------------- @@ -195,6 +196,17 @@ Runtime Config Options For example to select the legacy mode(RSS tag adder as XOR):: -w 0002:02:00.0,tag_as_xor=1 +- ``Max SPI for inbound inline IPsec`` (default ``1``) + + Max SPI supported for inbound inline IPsec processing can be specified by + ``ipsec_in_max_spi`` ``devargs`` parameter. + + For example:: + -w 0002:02:00.0,ipsec_in_max_spi=128 + + With the above configuration, application can enable inline IPsec processing + on 128 SAs (SPI 0-127). + .. note:: Above devarg parameters are configurable per device, user needs to pass the @@ -228,6 +240,14 @@ SDP interface support ~~~~~~~~~~~~~~~~~~~~~ OCTEON TX2 SDP interface support is limited to PF device, No VF support. +Inline Protocol Processing +~~~~~~~~~~~~~~~~~~~~~~~~~~ +``net_octeontx2`` pmd doesn't support the following features for packets to be +inline protocol processed. +- TSO offload +- VLAN/QinQ offload +- Fragmentation + Debugging Options ----------------- diff --git a/doc/guides/rel_notes/release_20_02.rst b/doc/guides/rel_notes/release_20_02.rst index 2c8ee326e4..9a159e458f 100644 --- a/doc/guides/rel_notes/release_20_02.rst +++ b/doc/guides/rel_notes/release_20_02.rst @@ -161,6 +161,15 @@ New Features armv8 crypto library is not used anymore. Library name is changed from armv8_crypto to AArch64crypto. +* **Added inline IPsec support to Marvell OCTEON TX2 PMD.** + + Added inline IPsec support to Marvell OCTEON TX2 PMD. With the feature, + applications would be able to offload entire IPsec offload to the hardware. + For the configured sessions, hardware will do the lookup and perform + decryption and IPsec transformation. For the outbound path, application + can submit a plain packet to the PMD, and it would be sent out on wire + after doing encryption and IPsec transformation of the packet. + * **Added Marvell OCTEON TX2 End Point rawdev PMD.** Added a new OCTEON TX2 rawdev PMD for End Point mode of operation. diff --git a/drivers/crypto/octeontx2/otx2_ipsec_fp.h b/drivers/crypto/octeontx2/otx2_ipsec_fp.h new file mode 100644 index 0000000000..bf4181ac9b --- /dev/null +++ b/drivers/crypto/octeontx2/otx2_ipsec_fp.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ + +#ifndef __OTX2_IPSEC_FP_H__ +#define __OTX2_IPSEC_FP_H__ + +struct otx2_ipsec_fp_sa_ctl { + rte_be32_t spi : 32; + uint64_t exp_proto_inter_frag : 8; + uint64_t rsvd_42_40 : 3; + uint64_t esn_en : 1; + uint64_t rsvd_45_44 : 2; + uint64_t encap_type : 2; + uint64_t enc_type : 3; + uint64_t rsvd_48 : 1; + uint64_t auth_type : 4; + uint64_t valid : 1; + uint64_t direction : 1; + uint64_t outer_ip_ver : 1; + uint64_t inner_ip_ver : 1; + uint64_t ipsec_mode : 1; + uint64_t ipsec_proto : 1; + uint64_t aes_key_len : 2; +}; + +struct otx2_ipsec_fp_in_sa { + /* w0 */ + struct otx2_ipsec_fp_sa_ctl ctl; + + /* w1 */ + uint8_t nonce[4]; /* Only for AES-GCM */ + uint32_t unused; + + /* w2 */ + uint32_t esn_low; + uint32_t esn_hi; + + /* w3-w6 */ + uint8_t cipher_key[32]; + + /* w7-w12 */ + uint8_t hmac_key[48]; + + RTE_STD_C11 + union { + void *userdata; + uint64_t udata64; + }; + + uint64_t reserved1; + uint64_t reserved2; +}; + +#endif /* __OTX2_IPSEC_FP_H__ */ diff --git a/drivers/net/octeontx2/Makefile b/drivers/net/octeontx2/Makefile index 8649f89479..0de43e36af 100644 --- a/drivers/net/octeontx2/Makefile +++ b/drivers/net/octeontx2/Makefile @@ -10,7 +10,9 @@ include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_pmd_octeontx2.a CFLAGS += $(WERROR_FLAGS) +CFLAGS += -I$(RTE_SDK)/drivers/common/cpt CFLAGS += -I$(RTE_SDK)/drivers/common/octeontx2 +CFLAGS += -I$(RTE_SDK)/drivers/crypto/octeontx2 CFLAGS += -I$(RTE_SDK)/drivers/mempool/octeontx2 CFLAGS += -I$(RTE_SDK)/drivers/net/octeontx2 CFLAGS += -O3 @@ -56,5 +58,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX2_PMD) += \ LDLIBS += -lrte_common_octeontx2 -lrte_mempool_octeontx2 -lrte_eal -lrte_net LDLIBS += -lrte_ethdev -lrte_bus_pci -lrte_kvargs -lrte_mbuf -lrte_mempool -lm +LDLIBS += -lrte_cryptodev -lrte_eventdev -lrte_security include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/net/octeontx2/meson.build b/drivers/net/octeontx2/meson.build index dfbf99a8e5..04cf58f5c9 100644 --- a/drivers/net/octeontx2/meson.build +++ b/drivers/net/octeontx2/meson.build @@ -25,7 +25,7 @@ sources = files('otx2_rx.c', 'otx2_ethdev_devargs.c' ) -deps += ['bus_pci', 'cryptodev', 'security'] +deps += ['bus_pci', 'cryptodev', 'eventdev', 'security'] deps += ['common_octeontx2', 'mempool_octeontx2'] cflags += ['-flax-vector-conversions'] @@ -41,3 +41,6 @@ foreach flag: extra_flags cflags += flag endif endforeach + +includes += include_directories('../../common/cpt') +includes += include_directories('../../crypto/octeontx2') diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c index 29426b83f0..e73033e41e 100644 --- a/drivers/net/octeontx2/otx2_ethdev.c +++ b/drivers/net/octeontx2/otx2_ethdev.c @@ -345,6 +345,10 @@ nix_cq_rq_init(struct rte_eth_dev *eth_dev, struct otx2_eth_dev *dev, aq->op = NIX_AQ_INSTOP_INIT; aq->rq.sso_ena = 0; + + if (rxq->offloads & DEV_RX_OFFLOAD_SECURITY) + aq->rq.ipsech_ena = 1; + aq->rq.cq = qid; /* RQ to CQ 1:1 mapped */ aq->rq.spb_ena = 0; aq->rq.lpb_aura = npa_lf_aura_handle_to_aura(mp->pool_id); @@ -1618,6 +1622,7 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev) /* Free the resources allocated from the previous configure */ if (dev->configured == 1) { + otx2_eth_sec_fini(eth_dev); otx2_nix_rxchan_bpid_cfg(eth_dev, false); otx2_nix_vlan_fini(eth_dev); otx2_nix_mc_addr_list_uninstall(eth_dev); @@ -1728,10 +1733,15 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev) goto cq_fini; } + /* Enable security */ + rc = otx2_eth_sec_init(eth_dev); + if (rc) + goto cq_fini; + rc = otx2_nix_mc_addr_list_install(eth_dev); if (rc < 0) { otx2_err("Failed to install mc address list rc=%d", rc); - goto cq_fini; + goto sec_fini; } /* @@ -1767,6 +1777,8 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev) uninstall_mc_list: otx2_nix_mc_addr_list_uninstall(eth_dev); +sec_fini: + otx2_eth_sec_fini(eth_dev); cq_fini: oxt2_nix_unregister_cq_irqs(eth_dev); q_irq_fini: @@ -2357,6 +2369,9 @@ otx2_eth_dev_uninit(struct rte_eth_dev *eth_dev, bool mbox_close) if (rc) otx2_err("Failed to cleanup npa lf, rc=%d", rc); + /* Disable security */ + otx2_eth_sec_fini(eth_dev); + /* Destroy security ctx */ otx2_eth_sec_ctx_destroy(eth_dev); diff --git a/drivers/net/octeontx2/otx2_ethdev.h b/drivers/net/octeontx2/otx2_ethdev.h index 49fed95e7f..5cb5953dcd 100644 --- a/drivers/net/octeontx2/otx2_ethdev.h +++ b/drivers/net/octeontx2/otx2_ethdev.h @@ -329,6 +329,8 @@ struct otx2_eth_dev { bool mc_tbl_set; struct otx2_nix_mc_filter_tbl mc_fltr_tbl; bool sdp_link; /* SDP flag */ + /* Inline IPsec params */ + uint16_t ipsec_in_max_spi; } __rte_cache_aligned; struct otx2_eth_txq { diff --git a/drivers/net/octeontx2/otx2_ethdev_devargs.c b/drivers/net/octeontx2/otx2_ethdev_devargs.c index ab1e14ea65..f29f01564f 100644 --- a/drivers/net/octeontx2/otx2_ethdev_devargs.c +++ b/drivers/net/octeontx2/otx2_ethdev_devargs.c @@ -63,6 +63,19 @@ parse_reta_size(const char *key, const char *value, void *extra_args) return 0; } +static int +parse_ipsec_in_max_spi(const char *key, const char *value, void *extra_args) +{ + RTE_SET_USED(key); + uint32_t val; + + val = atoi(value); + + *(uint16_t *)extra_args = val; + + return 0; +} + static int parse_flag(const char *key, const char *value, void *extra_args) { @@ -104,6 +117,7 @@ parse_switch_header_type(const char *key, const char *value, void *extra_args) } #define OTX2_RSS_RETA_SIZE "reta_size" +#define OTX2_IPSEC_IN_MAX_SPI "ipsec_in_max_spi" #define OTX2_SCL_ENABLE "scalar_enable" #define OTX2_MAX_SQB_COUNT "max_sqb_count" #define OTX2_FLOW_PREALLOC_SIZE "flow_prealloc_size" @@ -119,6 +133,7 @@ otx2_ethdev_parse_devargs(struct rte_devargs *devargs, struct otx2_eth_dev *dev) uint16_t flow_prealloc_size = 8; uint16_t switch_header_type = 0; uint16_t flow_max_priority = 3; + uint16_t ipsec_in_max_spi = 1; uint16_t scalar_enable = 0; uint16_t rss_tag_as_xor = 0; struct rte_kvargs *kvlist; @@ -132,6 +147,8 @@ otx2_ethdev_parse_devargs(struct rte_devargs *devargs, struct otx2_eth_dev *dev) rte_kvargs_process(kvlist, OTX2_RSS_RETA_SIZE, &parse_reta_size, &rss_size); + rte_kvargs_process(kvlist, OTX2_IPSEC_IN_MAX_SPI, + &parse_ipsec_in_max_spi, &ipsec_in_max_spi); rte_kvargs_process(kvlist, OTX2_SCL_ENABLE, &parse_flag, &scalar_enable); rte_kvargs_process(kvlist, OTX2_MAX_SQB_COUNT, @@ -147,6 +164,7 @@ otx2_ethdev_parse_devargs(struct rte_devargs *devargs, struct otx2_eth_dev *dev) rte_kvargs_free(kvlist); null_devargs: + dev->ipsec_in_max_spi = ipsec_in_max_spi; dev->scalar_ena = scalar_enable; dev->rss_tag_as_xor = rss_tag_as_xor; dev->max_sqb_count = sqb_count; @@ -162,6 +180,7 @@ exit: RTE_PMD_REGISTER_PARAM_STRING(net_octeontx2, OTX2_RSS_RETA_SIZE "=<64|128|256>" + OTX2_IPSEC_IN_MAX_SPI "=<1-65535>" OTX2_SCL_ENABLE "=1" OTX2_MAX_SQB_COUNT "=<8-512>" OTX2_FLOW_PREALLOC_SIZE "=<1-32>" diff --git a/drivers/net/octeontx2/otx2_ethdev_sec.c b/drivers/net/octeontx2/otx2_ethdev_sec.c index 80c5689a11..ed68152753 100644 --- a/drivers/net/octeontx2/otx2_ethdev_sec.c +++ b/drivers/net/octeontx2/otx2_ethdev_sec.c @@ -3,10 +3,35 @@ */ #include +#include #include +#include #include +#include "otx2_ethdev.h" #include "otx2_ethdev_sec.h" +#include "otx2_ipsec_fp.h" + +#define ETH_SEC_MAX_PKT_LEN 1450 + +struct eth_sec_tag_const { + RTE_STD_C11 + union { + struct { + uint32_t rsvd_11_0 : 12; + uint32_t port : 8; + uint32_t event_type : 4; + uint32_t rsvd_31_24 : 8; + }; + uint32_t u32; + }; +}; + +static inline void +in_sa_mz_name_get(char *name, int size, uint16_t port) +{ + snprintf(name, size, "otx2_ipsec_in_sadb_%u", port); +} int otx2_eth_sec_ctx_create(struct rte_eth_dev *eth_dev) @@ -33,3 +58,100 @@ otx2_eth_sec_ctx_destroy(struct rte_eth_dev *eth_dev) { rte_free(eth_dev->security_ctx); } + +static int +eth_sec_ipsec_cfg(struct rte_eth_dev *eth_dev, uint8_t tt) +{ + struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev); + uint16_t port = eth_dev->data->port_id; + struct nix_inline_ipsec_lf_cfg *req; + struct otx2_mbox *mbox = dev->mbox; + struct eth_sec_tag_const tag_const; + char name[RTE_MEMZONE_NAMESIZE]; + const struct rte_memzone *mz; + + in_sa_mz_name_get(name, RTE_MEMZONE_NAMESIZE, port); + mz = rte_memzone_lookup(name); + if (mz == NULL) + return -EINVAL; + + req = otx2_mbox_alloc_msg_nix_inline_ipsec_lf_cfg(mbox); + req->enable = 1; + req->sa_base_addr = mz->iova; + + req->ipsec_cfg0.tt = tt; + + tag_const.u32 = 0; + tag_const.event_type = RTE_EVENT_TYPE_ETHDEV; + tag_const.port = port; + req->ipsec_cfg0.tag_const = tag_const.u32; + + req->ipsec_cfg0.sa_pow2_size = + rte_log2_u32(sizeof(struct otx2_ipsec_fp_in_sa)); + req->ipsec_cfg0.lenm1_max = ETH_SEC_MAX_PKT_LEN - 1; + + req->ipsec_cfg1.sa_idx_w = rte_log2_u32(dev->ipsec_in_max_spi); + req->ipsec_cfg1.sa_idx_max = dev->ipsec_in_max_spi - 1; + + return otx2_mbox_process(mbox); +} + +int +otx2_eth_sec_init(struct rte_eth_dev *eth_dev) +{ + const size_t sa_width = sizeof(struct otx2_ipsec_fp_in_sa); + struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev); + uint16_t port = eth_dev->data->port_id; + char name[RTE_MEMZONE_NAMESIZE]; + const struct rte_memzone *mz; + int mz_sz, ret; + uint16_t nb_sa; + + RTE_BUILD_BUG_ON(sa_width < 32 || sa_width > 512 || + !RTE_IS_POWER_OF_2(sa_width)); + + if (!(dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY) && + !(dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY)) + return 0; + + nb_sa = dev->ipsec_in_max_spi; + mz_sz = nb_sa * sa_width; + in_sa_mz_name_get(name, RTE_MEMZONE_NAMESIZE, port); + mz = rte_memzone_reserve_aligned(name, mz_sz, rte_socket_id(), + RTE_MEMZONE_IOVA_CONTIG, OTX2_ALIGN); + + if (mz == NULL) { + otx2_err("Could not allocate inbound SA DB"); + return -ENOMEM; + } + + memset(mz->addr, 0, mz_sz); + + ret = eth_sec_ipsec_cfg(eth_dev, SSO_TT_ORDERED); + if (ret < 0) { + otx2_err("Could not configure inline IPsec"); + goto sec_fini; + } + + return 0; + +sec_fini: + otx2_err("Could not configure device for security"); + otx2_eth_sec_fini(eth_dev); + return ret; +} + +void +otx2_eth_sec_fini(struct rte_eth_dev *eth_dev) +{ + struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev); + uint16_t port = eth_dev->data->port_id; + char name[RTE_MEMZONE_NAMESIZE]; + + if (!(dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY) && + !(dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY)) + return; + + in_sa_mz_name_get(name, RTE_MEMZONE_NAMESIZE, port); + rte_memzone_free(rte_memzone_lookup(name)); +} diff --git a/drivers/net/octeontx2/otx2_ethdev_sec.h b/drivers/net/octeontx2/otx2_ethdev_sec.h index 4a925e9311..60d4a29e7e 100644 --- a/drivers/net/octeontx2/otx2_ethdev_sec.h +++ b/drivers/net/octeontx2/otx2_ethdev_sec.h @@ -11,4 +11,8 @@ int otx2_eth_sec_ctx_create(struct rte_eth_dev *eth_dev); void otx2_eth_sec_ctx_destroy(struct rte_eth_dev *eth_dev); +int otx2_eth_sec_init(struct rte_eth_dev *eth_dev); + +void otx2_eth_sec_fini(struct rte_eth_dev *eth_dev); + #endif /* __OTX2_ETHDEV_SEC_H__ */ -- 2.20.1