From patchwork Fri Sep 29 02:08:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chaoyong He X-Patchwork-Id: 132172 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A607142668; Fri, 29 Sep 2023 04:09:24 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 34F3040A6D; Fri, 29 Sep 2023 04:08:48 +0200 (CEST) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11on2118.outbound.protection.outlook.com [40.107.220.118]) by mails.dpdk.org (Postfix) with ESMTP id 51BE84069F for ; Fri, 29 Sep 2023 04:08:47 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ihgRkKc40/kWJ21nnUSTfkC4UswME07XgLJvHu6y/QPUrqlPXj9ILqbyfSvGFYXw3CIny9Rls28uhAFmXQyHjxgURbPVK6YxZyZ3Cdifi3e8EZyTGvCJuxiBof8GBfOZqMj0EZnUf9z0p8ZnEgbG3SCpFSgEDAgyOa0WBr1ZYV0lbh5lxY+u9zvtp4VphJT6Jv8KrBAq4RYeH/wCEF4pWO5yWoLQsWIXxAgnXCj7l4h5NcgpxmiogUjhnbD7K26xhNlq+KNfmcXh6La9d8wzT1prcsdCvLFc791UFjadHfp3AEBPm3uENAj11//63Byb9NkYiUYr5at3ltvDdyo5LQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=wwV7W7pEn1qVqfl2XHz6UB+s1y1DjF8mTFYxcZyXYVI=; b=mDZRt5bxQMYVt3c62NXwRsz+8ljphoXw+bb7eRUoWrwKXZJe9VvjOWCxH89N7ZFvx7Uv9whp/emggT8w8IiM5T+Sgmv8bAZ9wp/qR42PbvPiLpKcZibGVlepPyZok7i9xcznbWFg9fNO6Nmw4xPwuSxRH4pWRbTBjxb/TObgG1NH029uO1C18ANXKe9j1J6lcL/re7Pp5+UxCOlYAWGfQZtVN3sephXVSGs0BNeBUUgWUliCyeR004vx7bCR0cIyh38ilWA9Bta32XTOBjPNvb8yM8uAER6hWhUl15sRrHjc2Wma7Z1bjYB+OMQwnQjG9WtL3cyLEBzlAcj+y660+w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=corigine.com; dmarc=pass action=none header.from=corigine.com; dkim=pass header.d=corigine.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=corigine.onmicrosoft.com; s=selector2-corigine-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wwV7W7pEn1qVqfl2XHz6UB+s1y1DjF8mTFYxcZyXYVI=; b=euucsq8mNe6+Ngm03NvcJTAgtUy0brHGMWRbt7uHfeBg7ET+OTUtyPsWeDup4XoYqOc1Ht/GN0gbYdeV8sNR3dfz8JgO86d1pcNraXvUgPHrO7peYwkAa7MJfhxZwFCUMJz0aeeywIi/tBcHNIEci49d0EfMEFRvGRI17QMQ6hg= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=corigine.com; Received: from SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5) by CO3PR13MB5687.namprd13.prod.outlook.com (2603:10b6:303:17a::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6813.19; Fri, 29 Sep 2023 02:08:45 +0000 Received: from SJ0PR13MB5545.namprd13.prod.outlook.com ([fe80::28c0:63e2:ecd1:9314]) by SJ0PR13MB5545.namprd13.prod.outlook.com ([fe80::28c0:63e2:ecd1:9314%4]) with mapi id 15.20.6813.027; Fri, 29 Sep 2023 02:08:45 +0000 From: Chaoyong He To: dev@dpdk.org Cc: oss-drivers@corigine.com, Chang Miao , Shihong Wang , Chaoyong He Subject: [PATCH v3 6/9] net/nfp: create security session Date: Fri, 29 Sep 2023 10:08:07 +0800 Message-Id: <20230929020810.1219391-7-chaoyong.he@corigine.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20230929020810.1219391-1-chaoyong.he@corigine.com> References: <20230926024959.207098-1-chaoyong.he@corigine.com> <20230929020810.1219391-1-chaoyong.he@corigine.com> X-ClientProxiedBy: PH8PR07CA0028.namprd07.prod.outlook.com (2603:10b6:510:2cf::23) To SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR13MB5545:EE_|CO3PR13MB5687:EE_ X-MS-Office365-Filtering-Correlation-Id: e2702dec-6ee3-4455-49fc-08dbc091028a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: yfGPT0dgDTPuNe1xwO0z7bumg9uIu3raxRVcA9pE/GVoWEJuyJZp/mphNttshELHHCJFNAQd/Mqu0aShkKHiK07IrjbiURyuUZvM5tQUFkXn7TsIZKSmxFaaixvyvb+UGpvCHZwgBqXVOZ/3XnnooruCOt8bfqeYvqZTtSTjpvhdn2QJArJaVdidbdtp4V5FaYVY9OBhk/8I04lcxN2Nh+/LJtc0f0Dme4dZ2Mm4NofvaQO0KxB9c0eLU7Z2OKLZj5a78ASIsMenrroYPUmOM7wDtS4QuBmAsmUGezZfO9GkKiEriW8TzQonwBVOdrIqDUkqcIBGq7oG1RsRTppD0PInTX2Mg8kd8jipX6+DtEDMJJ+ehqbqISxVRUc0PWH7gv1eVylIK8+jPk7TCNIioRWCFuTH+JCteFUkRmiTgxdp6MG/XPeVE58hCVEFzDcCRGMJ4I83CO3BxzQRXaEBxhYFQBXVPTDsShY8gBlnYIpUeAfvZ7eetzXfvrwbd6YhSZhXBk3DI+m6zeJl5mSfR3rOm7iO7hbtC2nqlFsb0lY2HeyAhkgtJSanDdlLXJ7ViptDH2fjcFwkztvE1AIGG72IKN0hykUtrE9q2Rd1OUQFzwqcNnNhafuLgEj99xv624eeX5v+FU6grWKMonqXc30oDLN6s7pxLycPC7N4hF8= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SJ0PR13MB5545.namprd13.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(346002)(366004)(396003)(376002)(39830400003)(136003)(230922051799003)(451199024)(1800799009)(64100799003)(186009)(15650500001)(30864003)(2906002)(6916009)(316002)(54906003)(66946007)(66556008)(66476007)(44832011)(8936002)(8676002)(4326008)(41300700001)(5660300002)(2616005)(83380400001)(107886003)(1076003)(26005)(36756003)(86362001)(38100700002)(38350700002)(52116002)(6666004)(478600001)(6486002)(6512007)(6506007); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: WZo/o9SclOW7R7kf7fNBt9cfxDxZE0LlkO4C2fndjZROKzNUQNkZXrU4VehClN66FC/R/xdXElvdlr0qQ5DAPVrAS9/ohxY1v+w72NVrIjCgWZ8JjMH6p15AyjCeyH3z/egKtQ4aqu9t4vI2gbPXvJAX7cDp/JANopoRi8AmlY5WuzVrot1QBLFl5xdqyLYRKXmxBxz2qUn+7O7zXrv5Jj0LdaYMAu6vcycg7jqysf7FWUVPEgUCBMZuzy8NGpRSKjwXRXQs5HPOCUU0m62efhXaDpju8ou8ZIohvnmBUwVkDp27h1elJk++x/LCcCjYgEUjOwjdJwU7fcW7PjuIUvO/8AMyGKI/TOyL5wKN6b/OSaX9CTVRkD2sx+4NPQH3+9TuxD/APmfJI9x/JcRUqX4aBNrGKdHdwoCVwF6kdzaoOSn9OZ4ty61wMLsKY40sAmwVuJlPGehMYxrgh3wr9q0b0aCVdGOuq7mcYEdqIfjoodTxEpdIHRFmDpEntpFbm+HRFK2AaaNF/kJUCBN+paHemLV1dsyMZnOBXQeATDi6KXEvKlP/cVGKp9YuORHtae4YWK8qt+T/fUZJL48+N179jMIJoTJekejniP0me8/723jkoXABMk6PPnuXR8RAwXSzpUHOOYW/zN24ZJFAZeNAGNaD/uBaqHJPhByj1ZxdlyTE70eg+14YwXirKUNu07FSv8Xw7dkskw3blzGQXHkkLgBK0eSQ9ZIauNbIA43hkQet1YNuROrevFzzPoxi6ufIB9LLF4lR/Fk8ncc/NIMzOb3tFapyVSfJQ9qh8yvKX7AFyRLZwDQA3DzDbCvNNJRRhb4kV2EYCHzetQ47oX3QGfNHFplff66ZpfgnRmyjiWK3W0ZaOYSYkDyYDt7uT+ipGQc4WBQ8WVDZFswgT14pSlvgT4fn8Q1XhTf8xuwSkiaaQjgvxI4f5b4vo7Ni3zAXzxAJ+6oBQ/SttnBgrRUPGGGzNPOhNIYUijhkI9Be6B8rSJLjk4y29cibLtmwsp7KvJJYkbzPuPa5Jyxq6L9pzwW9RBSPloWZXQN1lUf5Bh6NV4IcowLKYu36/ct1RDN5lv9MqaXupC8b0pgg0K75wDj/dTlQh1w5l7Khjb8ImloFQXMuqI32dvJd1T0littGbCLjHLpVx2HTLMJne1IGbwASNFoPohY7lUL57gCroUsx9eaHDCY8OxBQtH4SG+kdfRMdjiEHCGLQ1epbcEj4np+5//fdKSgmtcT2ATwLMDqjKoPxQJRf32FqM3ZOhZYBWFAZebTP3oMGCk8SOGF7gx6KsYr0xpP6NF2mq3ENtwA/wUswkF3UOtnnDh/3Ss4aHPsIRFvq5ghl9M9xexNK5L0XH+uCwDuK2+I/YwobVRWERr3SCPQgU0kCEPcNls4CS+GwFsPRVsMFWKgIDy/zcmmHOYhj32AyB06b/6HTHGV/FklmFxjqlRkQihUS+2lSf/5x2rj/HfIHj9LqHEuJZT58pshWO+AcEr7QtPRU7iT8CUzmdZCLHoOWQizxLuIGGGmioEbo4sk4FSfzXxgCGCACCAI7g8VVhPsH66gaC56Fe0QJdrxOV4aJs22Io/fv7m8xR0ZLRaTTXe1tDQ== X-OriginatorOrg: corigine.com X-MS-Exchange-CrossTenant-Network-Message-Id: e2702dec-6ee3-4455-49fc-08dbc091028a X-MS-Exchange-CrossTenant-AuthSource: SJ0PR13MB5545.namprd13.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Sep 2023 02:08:45.1557 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: fe128f2c-073b-4c20-818e-7246a585940c X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: PdprusH/wQ8j3Vzd2DA6CQF5qzuSEjIpLB9/Vv4DHaUZTERB6O88B4QJExKZ3rTMJNkC9PWLEInxs/lYq6j/LVzjoP/C0QB09cd7Vfk82SI= X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO3PR13MB5687 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Chang Miao Create security session to manage IPsec protocol specific message and crypto parameters. This session support full protocol offload and inline crypto operation with NIC devices. Signed-off-by: Chang Miao Signed-off-by: Shihong Wang Reviewed-by: Chaoyong He --- drivers/net/nfp/nfp_ipsec.c | 698 ++++++++++++++++++++++++++++++++++++ 1 file changed, 698 insertions(+) diff --git a/drivers/net/nfp/nfp_ipsec.c b/drivers/net/nfp/nfp_ipsec.c index d4292c3b90..74627d2845 100644 --- a/drivers/net/nfp/nfp_ipsec.c +++ b/drivers/net/nfp/nfp_ipsec.c @@ -17,6 +17,8 @@ #include "nfp_logs.h" #include "nfp_rxtx.h" +#define NFP_UDP_ESP_PORT 4500 + static const struct rte_cryptodev_capabilities nfp_crypto_caps[] = { { .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, @@ -375,6 +377,62 @@ enum nfp_ipsec_cfg_msg_rsp_codes { NFP_IPSEC_CFG_MSG_SA_INVALID_CMD }; +enum nfp_ipsec_mode { + NFP_IPSEC_MODE_TRANSPORT, + NFP_IPSEC_MODE_TUNNEL, +}; + +enum nfp_ipsec_protocol { + NFP_IPSEC_PROTOCOL_AH, + NFP_IPSEC_PROTOCOL_ESP, +}; + +/* Cipher modes */ +enum nfp_ipsec_cimode { + NFP_IPSEC_CIMODE_ECB, + NFP_IPSEC_CIMODE_CBC, + NFP_IPSEC_CIMODE_CFB, + NFP_IPSEC_CIMODE_OFB, + NFP_IPSEC_CIMODE_CTR, +}; + +/* Hash types */ +enum nfp_ipsec_hash_type { + NFP_IPSEC_HASH_NONE, + NFP_IPSEC_HASH_MD5_96, + NFP_IPSEC_HASH_SHA1_96, + NFP_IPSEC_HASH_SHA256_96, + NFP_IPSEC_HASH_SHA384_96, + NFP_IPSEC_HASH_SHA512_96, + NFP_IPSEC_HASH_MD5_128, + NFP_IPSEC_HASH_SHA1_80, + NFP_IPSEC_HASH_SHA256_128, + NFP_IPSEC_HASH_SHA384_192, + NFP_IPSEC_HASH_SHA512_256, + NFP_IPSEC_HASH_GF128_128, + NFP_IPSEC_HASH_POLY1305_128, +}; + +/* Cipher types */ +enum nfp_ipsec_cipher_type { + NFP_IPSEC_CIPHER_NULL, + NFP_IPSEC_CIPHER_3DES, + NFP_IPSEC_CIPHER_AES128, + NFP_IPSEC_CIPHER_AES192, + NFP_IPSEC_CIPHER_AES256, + NFP_IPSEC_CIPHER_AES128_NULL, + NFP_IPSEC_CIPHER_AES192_NULL, + NFP_IPSEC_CIPHER_AES256_NULL, + NFP_IPSEC_CIPHER_CHACHA20, +}; + +/* Don't Fragment types */ +enum nfp_ipsec_df_type { + NFP_IPSEC_DF_CLEAR, + NFP_IPSEC_DF_SET, + NFP_IPSEC_DF_COPY, +}; + static int nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *hw, struct nfp_ipsec_msg *msg) @@ -427,6 +485,645 @@ nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *hw, return ret; } +/** + * Get valid SA index from SA table + * + * @param data + * SA table pointer + * @param sa_idx + * SA table index pointer + * + * @return + * Negative number on full or repeat, 0 on success + * + * Note: multiple sockets may create same SA session. + */ +static void +nfp_get_sa_entry(struct nfp_net_ipsec_data *data, + int *sa_idx) +{ + uint32_t i; + + for (i = 0; i < NFP_NET_IPSEC_MAX_SA_CNT; i++) { + if (data->sa_entries[i] == NULL) { + *sa_idx = i; + break; + } + } +} + +static void +nfp_aesgcm_iv_update(struct ipsec_add_sa *cfg, + uint16_t iv_len, + const char *iv_string) +{ + int i; + char *save; + char *iv_b; + char *iv_str; + uint8_t *cfg_iv; + + iv_str = strdup(iv_string); + cfg_iv = (uint8_t *)cfg->aesgcm_fields.iv; + + for (i = 0; i < iv_len; i++) { + iv_b = strtok_r(i ? NULL : iv_str, ",", &save); + if (iv_b == NULL) + break; + + cfg_iv[i] = strtoul(iv_b, NULL, 0); + } + + *(uint32_t *)cfg_iv = rte_be_to_cpu_32(*(uint32_t *)cfg_iv); + *(uint32_t *)&cfg_iv[4] = rte_be_to_cpu_32(*(uint32_t *)&cfg_iv[4]); + + free(iv_str); +} + +static int +set_aes_keylen(uint32_t key_length, + struct ipsec_add_sa *cfg) +{ + switch (key_length << 3) { + case 128: + cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES128; + break; + case 192: + cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES192; + break; + case 256: + cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES256; + break; + default: + PMD_DRV_LOG(ERR, "AES cipher key length is illegal!"); + return -EINVAL; + } + + return 0; +} + +/* Map rte_security_session_conf aead algo to NFP aead algo */ +static int +nfp_aead_map(struct rte_eth_dev *eth_dev, + struct rte_crypto_aead_xform *aead, + uint32_t key_length, + struct ipsec_add_sa *cfg) +{ + int ret; + uint32_t i; + uint32_t index; + uint16_t iv_len; + uint32_t offset; + uint32_t device_id; + const char *iv_str; + const uint32_t *key; + struct nfp_net_hw *hw; + + hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); + device_id = hw->device_id; + offset = 0; + + switch (aead->algo) { + case RTE_CRYPTO_AEAD_AES_GCM: + if (aead->digest_length != 16) { + PMD_DRV_LOG(ERR, "ICV must be 128bit with RTE_CRYPTO_AEAD_AES_GCM!"); + return -EINVAL; + } + + cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CTR; + cfg->ctrl_word.hash = NFP_IPSEC_HASH_GF128_128; + + ret = set_aes_keylen(key_length, cfg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to set AES_GCM key length!"); + return -EINVAL; + } + + break; + case RTE_CRYPTO_AEAD_CHACHA20_POLY1305: + if (device_id != PCI_DEVICE_ID_NFP3800_PF_NIC) { + PMD_DRV_LOG(ERR, "Unsupported aead CHACHA20_POLY1305 algorithm!"); + return -EINVAL; + } + + if (aead->digest_length != 16) { + PMD_DRV_LOG(ERR, "ICV must be 128bit with RTE_CRYPTO_AEAD_CHACHA20_POLY1305"); + return -EINVAL; + } + + /* Aead->alg_key_len includes 32-bit salt */ + if (key_length != 32) { + PMD_DRV_LOG(ERR, "Unsupported CHACHA20 key length"); + return -EINVAL; + } + + /* The CHACHA20's mode is not configured */ + cfg->ctrl_word.hash = NFP_IPSEC_HASH_POLY1305_128; + cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_CHACHA20; + break; + default: + PMD_DRV_LOG(ERR, "Unsupported aead algorithm!"); + return -EINVAL; + } + + key = (const uint32_t *)(aead->key.data); + + /* + * The CHACHA20's key order needs to be adjusted based on hardware design. + * Unadjusted order: {K0, K1, K2, K3, K4, K5, K6, K7} + * Adjusted order: {K4, K5, K6, K7, K0, K1, K2, K3} + */ + if (aead->algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) + offset = key_length / sizeof(cfg->cipher_key[0]) << 1; + + for (i = 0; i < key_length / sizeof(cfg->cipher_key[0]); i++) { + index = (i + offset) % (key_length / sizeof(cfg->cipher_key[0])); + cfg->cipher_key[index] = rte_cpu_to_be_32(*key++); + } + + /* + * The iv of the FW is equal to ESN by default. Reading the + * iv of the configuration information is not supported. + */ + iv_str = getenv("ETH_SEC_IV_OVR"); + if (iv_str != NULL) { + iv_len = aead->iv.length; + nfp_aesgcm_iv_update(cfg, iv_len, iv_str); + } + + return 0; +} + +/* Map rte_security_session_conf cipher algo to NFP cipher algo */ +static int +nfp_cipher_map(struct rte_eth_dev *eth_dev, + struct rte_crypto_cipher_xform *cipher, + uint32_t key_length, + struct ipsec_add_sa *cfg) +{ + int ret; + uint32_t i; + uint32_t device_id; + const uint32_t *key; + struct nfp_net_hw *hw; + + hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); + device_id = hw->device_id; + + switch (cipher->algo) { + case RTE_CRYPTO_CIPHER_NULL: + cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC; + cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_NULL; + break; + case RTE_CRYPTO_CIPHER_3DES_CBC: + if (device_id == PCI_DEVICE_ID_NFP3800_PF_NIC) { + PMD_DRV_LOG(ERR, "Unsupported 3DESCBC encryption algorithm!"); + return -EINVAL; + } + + cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC; + cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_3DES; + break; + case RTE_CRYPTO_CIPHER_AES_CBC: + cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC; + ret = set_aes_keylen(key_length, cfg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to set cipher key length!"); + return -EINVAL; + } + + break; + default: + PMD_DRV_LOG(ERR, "Unsupported cipher alg!"); + return -EINVAL; + } + + key = (const uint32_t *)(cipher->key.data); + if (key_length > sizeof(cfg->cipher_key)) { + PMD_DRV_LOG(ERR, "Insufficient space for offloaded key"); + return -EINVAL; + } + + for (i = 0; i < key_length / sizeof(cfg->cipher_key[0]); i++) + cfg->cipher_key[i] = rte_cpu_to_be_32(*key++); + + return 0; +} + +static void +set_md5hmac(struct ipsec_add_sa *cfg, + uint32_t *digest_length) +{ + switch (*digest_length) { + case 96: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_MD5_96; + break; + case 128: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_MD5_128; + break; + default: + *digest_length = 0; + } +} + +static void +set_sha1hmac(struct ipsec_add_sa *cfg, + uint32_t *digest_length) +{ + switch (*digest_length) { + case 96: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA1_96; + break; + case 80: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA1_80; + break; + default: + *digest_length = 0; + } +} + +static void +set_sha2_256hmac(struct ipsec_add_sa *cfg, + uint32_t *digest_length) +{ + switch (*digest_length) { + case 96: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA256_96; + break; + case 128: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA256_128; + break; + default: + *digest_length = 0; + } +} + +static void +set_sha2_384hmac(struct ipsec_add_sa *cfg, + uint32_t *digest_length) +{ + switch (*digest_length) { + case 96: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA384_96; + break; + case 192: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA384_192; + break; + default: + *digest_length = 0; + } +} + +static void +set_sha2_512hmac(struct ipsec_add_sa *cfg, + uint32_t *digest_length) +{ + switch (*digest_length) { + case 96: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA512_96; + break; + case 256: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA512_256; + break; + default: + *digest_length = 0; + } +} + +/* Map rte_security_session_conf auth algo to NFP auth algo */ +static int +nfp_auth_map(struct rte_eth_dev *eth_dev, + struct rte_crypto_auth_xform *auth, + uint32_t digest_length, + struct ipsec_add_sa *cfg) +{ + uint32_t i; + uint8_t key_length; + uint32_t device_id; + const uint32_t *key; + struct nfp_net_hw *hw; + + if (digest_length == 0) { + PMD_DRV_LOG(ERR, "Auth digest length is illegal!"); + return -EINVAL; + } + + hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); + device_id = hw->device_id; + digest_length = digest_length << 3; + + switch (auth->algo) { + case RTE_CRYPTO_AUTH_NULL: + cfg->ctrl_word.hash = NFP_IPSEC_HASH_NONE; + digest_length = 1; + break; + case RTE_CRYPTO_AUTH_MD5_HMAC: + if (device_id == PCI_DEVICE_ID_NFP3800_PF_NIC) { + PMD_DRV_LOG(ERR, "Unsupported MD5HMAC authentication algorithm!"); + return -EINVAL; + } + + set_md5hmac(cfg, &digest_length); + break; + case RTE_CRYPTO_AUTH_SHA1_HMAC: + set_sha1hmac(cfg, &digest_length); + break; + case RTE_CRYPTO_AUTH_SHA256_HMAC: + set_sha2_256hmac(cfg, &digest_length); + break; + case RTE_CRYPTO_AUTH_SHA384_HMAC: + set_sha2_384hmac(cfg, &digest_length); + break; + case RTE_CRYPTO_AUTH_SHA512_HMAC: + set_sha2_512hmac(cfg, &digest_length); + break; + default: + PMD_DRV_LOG(ERR, "Unsupported auth alg!"); + return -EINVAL; + } + + if (digest_length == 0) { + PMD_DRV_LOG(ERR, "Unsupported authentication algorithm digest length"); + return -EINVAL; + } + + key = (const uint32_t *)(auth->key.data); + key_length = auth->key.length; + if (key_length > sizeof(cfg->auth_key)) { + PMD_DRV_LOG(ERR, "Insufficient space for offloaded auth key!"); + return -EINVAL; + } + + for (i = 0; i < key_length / sizeof(cfg->auth_key[0]); i++) + cfg->auth_key[i] = rte_cpu_to_be_32(*key++); + + return 0; +} + +static int +nfp_crypto_msg_build(struct rte_eth_dev *eth_dev, + struct rte_security_session_conf *conf, + struct nfp_ipsec_msg *msg) +{ + int ret; + struct ipsec_add_sa *cfg; + struct rte_crypto_sym_xform *cur; + struct rte_crypto_sym_xform *next; + enum rte_security_ipsec_sa_direction direction; + + cur = conf->crypto_xform; + if (cur == NULL) { + PMD_DRV_LOG(ERR, "Unsupported crypto_xform is NULL!"); + return -EINVAL; + } + + next = cur->next; + direction = conf->ipsec.direction; + cfg = &msg->cfg_add_sa; + + switch (cur->type) { + case RTE_CRYPTO_SYM_XFORM_AEAD: + /* Aead transforms can be used for either inbound/outbound IPsec SAs */ + if (next != NULL) { + PMD_DRV_LOG(ERR, "Next crypto_xform type should be NULL!"); + return -EINVAL; + } + + ret = nfp_aead_map(eth_dev, &cur->aead, cur->aead.key.length, cfg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to map aead alg!"); + return ret; + } + + cfg->aesgcm_fields.salt = rte_cpu_to_be_32(conf->ipsec.salt); + break; + case RTE_CRYPTO_SYM_XFORM_AUTH: + /* Only support Auth + Cipher for inbound */ + if (direction != RTE_SECURITY_IPSEC_SA_DIR_INGRESS) { + PMD_DRV_LOG(ERR, "Direction should be INGRESS, but it is not!"); + return -EINVAL; + } + + if (next == NULL || next->type != RTE_CRYPTO_SYM_XFORM_CIPHER) { + PMD_DRV_LOG(ERR, "Next crypto_xfrm should be cipher, but it is not!"); + return -EINVAL; + } + + ret = nfp_auth_map(eth_dev, &cur->auth, cur->auth.digest_length, cfg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to map auth alg!"); + return ret; + } + + ret = nfp_cipher_map(eth_dev, &next->cipher, next->cipher.key.length, cfg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to map cipher alg!"); + return ret; + } + + break; + case RTE_CRYPTO_SYM_XFORM_CIPHER: + /* Only support Cipher + Auth for outbound */ + if (direction != RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { + PMD_DRV_LOG(ERR, "Direction should be EGRESS, but it is not!"); + return -EINVAL; + } + + if (next == NULL || next->type != RTE_CRYPTO_SYM_XFORM_AUTH) { + PMD_DRV_LOG(ERR, "Next crypto_xfrm should be auth, but it is not!"); + return -EINVAL; + } + + ret = nfp_cipher_map(eth_dev, &cur->cipher, cur->cipher.key.length, cfg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to map cipher alg!"); + return ret; + } + + ret = nfp_auth_map(eth_dev, &next->auth, next->auth.digest_length, cfg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to map auth alg!"); + return ret; + } + + break; + default: + PMD_DRV_LOG(ERR, "Unsupported crypto_xform type!"); + return -EINVAL; + } + + return 0; +} + +static int +nfp_ipsec_msg_build(struct rte_eth_dev *eth_dev, + struct rte_security_session_conf *conf, + struct nfp_ipsec_msg *msg) +{ + int ret; + struct ipsec_add_sa *cfg; + enum rte_security_ipsec_tunnel_type type; + + cfg = &msg->cfg_add_sa; + cfg->spi = conf->ipsec.spi; + cfg->pmtu_limit = 0xffff; + + /* + * UDP encapsulation + * + * 1: Do UDP encapsulation/decapsulation + * 0: No UDP encapsulation + */ + if (conf->ipsec.options.udp_encap == 1) { + cfg->udp_enable = 1; + cfg->natt_dst_port = NFP_UDP_ESP_PORT; + cfg->natt_src_port = NFP_UDP_ESP_PORT; + } + + if (conf->ipsec.options.copy_df == 1) + cfg->df_ctrl = NFP_IPSEC_DF_COPY; + else if (conf->ipsec.tunnel.ipv4.df != 0) + cfg->df_ctrl = NFP_IPSEC_DF_SET; + else + cfg->df_ctrl = NFP_IPSEC_DF_CLEAR; + + switch (conf->action_type) { + case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: + cfg->ctrl_word.encap_dsbl = 1; + break; + case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: + cfg->ctrl_word.encap_dsbl = 0; + break; + default: + PMD_DRV_LOG(ERR, "Unsupported IPsec action for offload, action: %d", + conf->action_type); + return -EINVAL; + } + + switch (conf->ipsec.proto) { + case RTE_SECURITY_IPSEC_SA_PROTO_ESP: + cfg->ctrl_word.proto = NFP_IPSEC_PROTOCOL_ESP; + break; + case RTE_SECURITY_IPSEC_SA_PROTO_AH: + cfg->ctrl_word.proto = NFP_IPSEC_PROTOCOL_AH; + break; + default: + PMD_DRV_LOG(ERR, "Unsupported IPsec protocol for offload, protocol: %d", + conf->ipsec.proto); + return -EINVAL; + } + + switch (conf->ipsec.mode) { + case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL: + type = conf->ipsec.tunnel.type; + cfg->ctrl_word.mode = NFP_IPSEC_MODE_TUNNEL; + if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) { + cfg->src_ip.v4 = conf->ipsec.tunnel.ipv4.src_ip; + cfg->dst_ip.v4 = conf->ipsec.tunnel.ipv4.dst_ip; + cfg->ipv6 = 0; + } else if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) { + cfg->src_ip.v6 = conf->ipsec.tunnel.ipv6.src_addr; + cfg->dst_ip.v6 = conf->ipsec.tunnel.ipv6.dst_addr; + cfg->ipv6 = 1; + } else { + PMD_DRV_LOG(ERR, "Unsupported address family!"); + return -EINVAL; + } + + break; + case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT: + type = conf->ipsec.tunnel.type; + cfg->ctrl_word.mode = NFP_IPSEC_MODE_TRANSPORT; + if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) { + memset(&cfg->src_ip, 0, sizeof(cfg->src_ip)); + cfg->ipv6 = 0; + } else if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) { + memset(&cfg->src_ip, 0, sizeof(cfg->src_ip)); + cfg->ipv6 = 1; + } else { + PMD_DRV_LOG(ERR, "Unsupported address family!"); + return -EINVAL; + } + + break; + default: + PMD_DRV_LOG(ERR, "Unsupported IPsec mode for offload, mode: %d", + conf->ipsec.mode); + return -EINVAL; + } + + ret = nfp_crypto_msg_build(eth_dev, conf, msg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to build auth/crypto/aead msg!"); + return ret; + } + + return 0; +} + +static int +nfp_crypto_create_session(void *device, + struct rte_security_session_conf *conf, + struct rte_security_session *session) +{ + int ret; + int sa_idx; + struct nfp_net_hw *hw; + struct nfp_ipsec_msg msg; + struct rte_eth_dev *eth_dev; + struct nfp_ipsec_session *priv_session; + + /* Only support IPsec at present */ + if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) { + PMD_DRV_LOG(ERR, "Unsupported non-IPsec offload!"); + return -EINVAL; + } + + sa_idx = -1; + eth_dev = device; + priv_session = SECURITY_GET_SESS_PRIV(session); + hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); + + if (hw->ipsec_data->sa_free_cnt == 0) { + PMD_DRV_LOG(ERR, "No space in SA table, spi: %d", conf->ipsec.spi); + return -EINVAL; + } + + nfp_get_sa_entry(hw->ipsec_data, &sa_idx); + + if (sa_idx < 0) { + PMD_DRV_LOG(ERR, "Failed to get SA entry!"); + return -EINVAL; + } + + memset(&msg, 0, sizeof(msg)); + ret = nfp_ipsec_msg_build(eth_dev, conf, &msg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to build IPsec msg!"); + return -EINVAL; + } + + msg.cmd = NFP_IPSEC_CFG_MSG_ADD_SA; + msg.sa_idx = sa_idx; + ret = nfp_ipsec_cfg_cmd_issue(hw, &msg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Failed to add SA to nic"); + return -EINVAL; + } + + priv_session->action = conf->action_type; + priv_session->ipsec = conf->ipsec; + priv_session->msg = msg.cfg_add_sa; + priv_session->sa_index = sa_idx; + priv_session->dev = eth_dev; + priv_session->user_data = conf->userdata; + + hw->ipsec_data->sa_free_cnt--; + hw->ipsec_data->sa_entries[sa_idx] = priv_session; + + return 0; +} + /** * Get discards packet statistics for each SA * @@ -517,6 +1214,7 @@ nfp_security_session_get_size(void *device __rte_unused) } static const struct rte_security_ops nfp_security_ops = { + .session_create = nfp_crypto_create_session, .session_get_size = nfp_security_session_get_size, .session_stats_get = nfp_security_session_get_stats, .capabilities_get = nfp_crypto_capabilities_get,