get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/48146/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 48146,
    "url": "http://patches.dpdk.org/api/patches/48146/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1542326031-5263-5-git-send-email-konstantin.ananyev@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1542326031-5263-5-git-send-email-konstantin.ananyev@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1542326031-5263-5-git-send-email-konstantin.ananyev@intel.com",
    "date": "2018-11-15T23:53:46",
    "name": "[4/9] lib: introduce ipsec library",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "1bbfa8124ff216869f85ca2ddb77b0fe813d5926",
    "submitter": {
        "id": 33,
        "url": "http://patches.dpdk.org/api/people/33/?format=api",
        "name": "Ananyev, Konstantin",
        "email": "konstantin.ananyev@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1542326031-5263-5-git-send-email-konstantin.ananyev@intel.com/mbox/",
    "series": [
        {
            "id": 2454,
            "url": "http://patches.dpdk.org/api/series/2454/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=2454",
            "date": "2018-11-15T23:53:46",
            "name": null,
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/2454/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/48146/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/48146/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id BDAAC4F91;\n\tFri, 16 Nov 2018 00:54:11 +0100 (CET)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id C78321D7\n\tfor <dev@dpdk.org>; Fri, 16 Nov 2018 00:54:05 +0100 (CET)",
            "from orsmga007.jf.intel.com ([10.7.209.58])\n\tby orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t15 Nov 2018 15:54:05 -0800",
            "from sivswdev08.ir.intel.com (HELO localhost.localdomain)\n\t([10.237.217.47])\n\tby orsmga007.jf.intel.com with ESMTP; 15 Nov 2018 15:54:04 -0800"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.56,238,1539673200\"; d=\"scan'208\";a=\"89697372\"",
        "From": "Konstantin Ananyev <konstantin.ananyev@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "Konstantin Ananyev <konstantin.ananyev@intel.com>,\n\tMohammad Abdul Awal <mohammad.abdul.awal@intel.com>",
        "Date": "Thu, 15 Nov 2018 23:53:46 +0000",
        "Message-Id": "<1542326031-5263-5-git-send-email-konstantin.ananyev@intel.com>",
        "X-Mailer": "git-send-email 1.7.0.7",
        "In-Reply-To": "<1535129598-27301-1-git-send-email-konstantin.ananyev@intel.com>",
        "References": "<1535129598-27301-1-git-send-email-konstantin.ananyev@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 4/9] lib: introduce ipsec library",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Introduce librte_ipsec library.\nThe library is supposed to utilize existing DPDK crypto-dev and\nsecurity API to provide application with transparent IPsec processing API.\nThat initial commit provides some base API to manage\nIPsec Security Association (SA) object.\n\nSigned-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>\nSigned-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\n---\n config/common_base                     |   5 +\n lib/Makefile                           |   2 +\n lib/librte_ipsec/Makefile              |  24 ++\n lib/librte_ipsec/ipsec_sqn.h           |  48 ++++\n lib/librte_ipsec/meson.build           |  10 +\n lib/librte_ipsec/rte_ipsec_sa.h        | 139 +++++++++++\n lib/librte_ipsec/rte_ipsec_version.map |  10 +\n lib/librte_ipsec/sa.c                  | 307 +++++++++++++++++++++++++\n lib/librte_ipsec/sa.h                  |  77 +++++++\n lib/meson.build                        |   2 +\n mk/rte.app.mk                          |   2 +\n 11 files changed, 626 insertions(+)\n create mode 100644 lib/librte_ipsec/Makefile\n create mode 100644 lib/librte_ipsec/ipsec_sqn.h\n create mode 100644 lib/librte_ipsec/meson.build\n create mode 100644 lib/librte_ipsec/rte_ipsec_sa.h\n create mode 100644 lib/librte_ipsec/rte_ipsec_version.map\n create mode 100644 lib/librte_ipsec/sa.c\n create mode 100644 lib/librte_ipsec/sa.h",
    "diff": "diff --git a/config/common_base b/config/common_base\nindex d12ae98bc..32499d772 100644\n--- a/config/common_base\n+++ b/config/common_base\n@@ -925,6 +925,11 @@ CONFIG_RTE_LIBRTE_BPF=y\n # allow load BPF from ELF files (requires libelf)\n CONFIG_RTE_LIBRTE_BPF_ELF=n\n \n+#\n+# Compile librte_ipsec\n+#\n+CONFIG_RTE_LIBRTE_IPSEC=y\n+\n #\n # Compile the test application\n #\ndiff --git a/lib/Makefile b/lib/Makefile\nindex b7370ef97..5dc774604 100644\n--- a/lib/Makefile\n+++ b/lib/Makefile\n@@ -106,6 +106,8 @@ DEPDIRS-librte_gso := librte_eal librte_mbuf librte_ethdev librte_net\n DEPDIRS-librte_gso += librte_mempool\n DIRS-$(CONFIG_RTE_LIBRTE_BPF) += librte_bpf\n DEPDIRS-librte_bpf := librte_eal librte_mempool librte_mbuf librte_ethdev\n+DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += librte_ipsec\n+DEPDIRS-librte_ipsec := librte_eal librte_mbuf librte_cryptodev librte_security\n DIRS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += librte_telemetry\n DEPDIRS-librte_telemetry := librte_eal librte_metrics librte_ethdev\n \ndiff --git a/lib/librte_ipsec/Makefile b/lib/librte_ipsec/Makefile\nnew file mode 100644\nindex 000000000..7758dcc6d\n--- /dev/null\n+++ b/lib/librte_ipsec/Makefile\n@@ -0,0 +1,24 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2018 Intel Corporation\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+# library name\n+LIB = librte_ipsec.a\n+\n+CFLAGS += -O3\n+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)\n+CFLAGS += -DALLOW_EXPERIMENTAL_API\n+LDLIBS += -lrte_eal -lrte_mbuf -lrte_cryptodev -lrte_security\n+\n+EXPORT_MAP := rte_ipsec_version.map\n+\n+LIBABIVER := 1\n+\n+# all source are stored in SRCS-y\n+SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += sa.c\n+\n+# install header files\n+SYMLINK-$(CONFIG_RTE_LIBRTE_IPSEC)-include += rte_ipsec_sa.h\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/lib/librte_ipsec/ipsec_sqn.h b/lib/librte_ipsec/ipsec_sqn.h\nnew file mode 100644\nindex 000000000..4471814f9\n--- /dev/null\n+++ b/lib/librte_ipsec/ipsec_sqn.h\n@@ -0,0 +1,48 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Intel Corporation\n+ */\n+\n+#ifndef _IPSEC_SQN_H_\n+#define _IPSEC_SQN_H_\n+\n+#define WINDOW_BUCKET_BITS\t\t6 /* uint64_t */\n+#define WINDOW_BUCKET_SIZE\t\t(1 << WINDOW_BUCKET_BITS)\n+#define WINDOW_BIT_LOC_MASK\t\t(WINDOW_BUCKET_SIZE - 1)\n+\n+/* minimum number of bucket, power of 2*/\n+#define WINDOW_BUCKET_MIN\t\t2\n+#define WINDOW_BUCKET_MAX\t\t(INT16_MAX + 1)\n+\n+#define IS_ESN(sa)\t((sa)->sqn_mask == UINT64_MAX)\n+\n+/*\n+ * for given size, calculate required number of buckets.\n+ */\n+static uint32_t\n+replay_num_bucket(uint32_t wsz)\n+{\n+\tuint32_t nb;\n+\n+\tnb = rte_align32pow2(RTE_ALIGN_MUL_CEIL(wsz, WINDOW_BUCKET_SIZE) /\n+\t\tWINDOW_BUCKET_SIZE);\n+\tnb = RTE_MAX(nb, (uint32_t)WINDOW_BUCKET_MIN);\n+\n+\treturn nb;\n+}\n+\n+/**\n+ * Based on number of buckets calculated required size for the\n+ * structure that holds replay window and sequnce number (RSN) information.\n+ */\n+static size_t\n+rsn_size(uint32_t nb_bucket)\n+{\n+\tsize_t sz;\n+\tstruct replay_sqn *rsn;\n+\n+\tsz = sizeof(*rsn) + nb_bucket * sizeof(rsn->window[0]);\n+\tsz = RTE_ALIGN_CEIL(sz, RTE_CACHE_LINE_SIZE);\n+\treturn sz;\n+}\n+\n+#endif /* _IPSEC_SQN_H_ */\ndiff --git a/lib/librte_ipsec/meson.build b/lib/librte_ipsec/meson.build\nnew file mode 100644\nindex 000000000..52c78eaeb\n--- /dev/null\n+++ b/lib/librte_ipsec/meson.build\n@@ -0,0 +1,10 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2018 Intel Corporation\n+\n+allow_experimental_apis = true\n+\n+sources=files('sa.c')\n+\n+install_headers = files('rte_ipsec_sa.h')\n+\n+deps += ['mbuf', 'net', 'cryptodev', 'security']\ndiff --git a/lib/librte_ipsec/rte_ipsec_sa.h b/lib/librte_ipsec/rte_ipsec_sa.h\nnew file mode 100644\nindex 000000000..4e36fd99b\n--- /dev/null\n+++ b/lib/librte_ipsec/rte_ipsec_sa.h\n@@ -0,0 +1,139 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Intel Corporation\n+ */\n+\n+#ifndef _RTE_IPSEC_SA_H_\n+#define _RTE_IPSEC_SA_H_\n+\n+/**\n+ * @file rte_ipsec_sa.h\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Defines API to manage IPsec Security Association (SA) objects.\n+ */\n+\n+#include <rte_common.h>\n+#include <rte_cryptodev.h>\n+#include <rte_security.h>\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+/**\n+ * An opaque structure to represent Security Association (SA).\n+ */\n+struct rte_ipsec_sa;\n+\n+/**\n+ * SA initialization parameters.\n+ */\n+struct rte_ipsec_sa_prm {\n+\n+\tuint64_t userdata; /**< provided and interpreted by user */\n+\tuint64_t flags;  /**< see RTE_IPSEC_SAFLAG_* below */\n+\t/** ipsec configuration */\n+\tstruct rte_security_ipsec_xform ipsec_xform;\n+\tstruct rte_crypto_sym_xform *crypto_xform;\n+\tunion {\n+\t\tstruct {\n+\t\t\tuint8_t hdr_len;     /**< tunnel header len */\n+\t\t\tuint8_t hdr_l3_off;  /**< offset for IPv4/IPv6 header */\n+\t\t\tuint8_t next_proto;  /**< next header protocol */\n+\t\t\tconst void *hdr;     /**< tunnel header template */\n+\t\t} tun; /**< tunnel mode repated parameters */\n+\t\tstruct {\n+\t\t\tuint8_t proto;  /**< next header protocol */\n+\t\t} trs; /**< transport mode repated parameters */\n+\t};\n+\n+\tuint32_t replay_win_sz;\n+\t/**< window size to enable sequence replay attack handling.\n+\t * Replay checking is disabled if the window size is 0.\n+\t */\n+};\n+\n+/**\n+ * SA type is an 64-bit value that contain the following information:\n+ * - IP version (IPv4/IPv6)\n+ * - IPsec proto (ESP/AH)\n+ * - inbound/outbound\n+ * - mode (TRANSPORT/TUNNEL)\n+ * - for TUNNEL outer IP version (IPv4/IPv6)\n+ * ...\n+ */\n+\n+enum {\n+\tRTE_SATP_LOG_IPV,\n+\tRTE_SATP_LOG_PROTO,\n+\tRTE_SATP_LOG_DIR,\n+\tRTE_SATP_LOG_MODE,\n+\tRTE_SATP_LOG_NUM\n+};\n+\n+#define RTE_IPSEC_SATP_IPV_MASK\t\t(1ULL << RTE_SATP_LOG_IPV)\n+#define RTE_IPSEC_SATP_IPV4\t\t(0ULL << RTE_SATP_LOG_IPV)\n+#define RTE_IPSEC_SATP_IPV6\t\t(1ULL << RTE_SATP_LOG_IPV)\n+\n+#define RTE_IPSEC_SATP_PROTO_MASK\t(1ULL << RTE_SATP_LOG_PROTO)\n+#define RTE_IPSEC_SATP_PROTO_AH\t\t(0ULL << RTE_SATP_LOG_PROTO)\n+#define RTE_IPSEC_SATP_PROTO_ESP\t(1ULL << RTE_SATP_LOG_PROTO)\n+\n+#define RTE_IPSEC_SATP_DIR_MASK\t\t(1ULL << RTE_SATP_LOG_DIR)\n+#define RTE_IPSEC_SATP_DIR_IB\t\t(0ULL << RTE_SATP_LOG_DIR)\n+#define RTE_IPSEC_SATP_DIR_OB\t\t(1ULL << RTE_SATP_LOG_DIR)\n+\n+#define RTE_IPSEC_SATP_MODE_MASK\t(3ULL << RTE_SATP_LOG_MODE)\n+#define RTE_IPSEC_SATP_MODE_TRANS\t(0ULL << RTE_SATP_LOG_MODE)\n+#define RTE_IPSEC_SATP_MODE_TUNLV4\t(1ULL << RTE_SATP_LOG_MODE)\n+#define RTE_IPSEC_SATP_MODE_TUNLV6\t(2ULL << RTE_SATP_LOG_MODE)\n+\n+/**\n+ * get type of given SA\n+ * @return\n+ *   SA type value.\n+ */\n+uint64_t __rte_experimental\n+rte_ipsec_sa_type(const struct rte_ipsec_sa *sa);\n+\n+/**\n+ * Calculate requied SA size based on provided input parameters.\n+ * @param prm\n+ *   Parameters that wil be used to initialise SA object.\n+ * @return\n+ *   - Actual size required for SA with given parameters.\n+ *   - -EINVAL if the parameters are invalid.\n+ */\n+int __rte_experimental\n+rte_ipsec_sa_size(const struct rte_ipsec_sa_prm *prm);\n+\n+/**\n+ * initialise SA based on provided input parameters.\n+ * @param sa\n+ *   SA object to initialise.\n+ * @param prm\n+ *   Parameters used to initialise given SA object.\n+ * @param size\n+ *   size of the provided buffer for SA.\n+ * @return\n+ *   - Actual size of SA object if operation completed successfully.\n+ *   - -EINVAL if the parameters are invalid.\n+ *   - -ENOSPC if the size of the provided buffer is not big enough.\n+ */\n+int __rte_experimental\n+rte_ipsec_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,\n+\tuint32_t size);\n+\n+/**\n+ * cleanup SA\n+ * @param sa\n+ *   Pointer to SA object to de-initialize.\n+ */\n+void __rte_experimental\n+rte_ipsec_sa_fini(struct rte_ipsec_sa *sa);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_IPSEC_SA_H_ */\ndiff --git a/lib/librte_ipsec/rte_ipsec_version.map b/lib/librte_ipsec/rte_ipsec_version.map\nnew file mode 100644\nindex 000000000..1a66726b8\n--- /dev/null\n+++ b/lib/librte_ipsec/rte_ipsec_version.map\n@@ -0,0 +1,10 @@\n+EXPERIMENTAL {\n+\tglobal:\n+\n+\trte_ipsec_sa_fini;\n+\trte_ipsec_sa_init;\n+\trte_ipsec_sa_size;\n+\trte_ipsec_sa_type;\n+\n+\tlocal: *;\n+};\ndiff --git a/lib/librte_ipsec/sa.c b/lib/librte_ipsec/sa.c\nnew file mode 100644\nindex 000000000..c814e5384\n--- /dev/null\n+++ b/lib/librte_ipsec/sa.c\n@@ -0,0 +1,307 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Intel Corporation\n+ */\n+\n+#include <rte_ipsec_sa.h>\n+#include <rte_esp.h>\n+#include <rte_ip.h>\n+#include <rte_errno.h>\n+\n+#include \"sa.h\"\n+#include \"ipsec_sqn.h\"\n+\n+/* some helper structures */\n+struct crypto_xform {\n+\tstruct rte_crypto_auth_xform *auth;\n+\tstruct rte_crypto_cipher_xform *cipher;\n+\tstruct rte_crypto_aead_xform *aead;\n+};\n+\n+\n+static int\n+check_crypto_xform(struct crypto_xform *xform)\n+{\n+\tuintptr_t p;\n+\n+\tp = (uintptr_t)xform->auth | (uintptr_t)xform->cipher;\n+\n+\t/* either aead or both auth and cipher should be not NULLs */\n+\tif (xform->aead) {\n+\t\tif (p)\n+\t\t\treturn -EINVAL;\n+\t} else if (p == (uintptr_t)xform->auth) {\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+fill_crypto_xform(struct crypto_xform *xform,\n+\tconst struct rte_ipsec_sa_prm *prm)\n+{\n+\tstruct rte_crypto_sym_xform *xf;\n+\n+\tmemset(xform, 0, sizeof(*xform));\n+\n+\tfor (xf = prm->crypto_xform; xf != NULL; xf = xf->next) {\n+\t\tif (xf->type == RTE_CRYPTO_SYM_XFORM_AUTH) {\n+\t\t\tif (xform->auth != NULL)\n+\t\t\t\treturn -EINVAL;\n+\t\t\txform->auth = &xf->auth;\n+\t\t} else if (xf->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {\n+\t\t\tif (xform->cipher != NULL)\n+\t\t\t\treturn -EINVAL;\n+\t\t\txform->cipher = &xf->cipher;\n+\t\t} else if (xf->type == RTE_CRYPTO_SYM_XFORM_AEAD) {\n+\t\t\tif (xform->aead != NULL)\n+\t\t\t\treturn -EINVAL;\n+\t\t\txform->aead = &xf->aead;\n+\t\t} else\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\treturn check_crypto_xform(xform);\n+}\n+\n+uint64_t __rte_experimental\n+rte_ipsec_sa_type(const struct rte_ipsec_sa *sa)\n+{\n+\treturn sa->type;\n+}\n+\n+static int32_t\n+ipsec_sa_size(uint32_t wsz, uint64_t type, uint32_t *nb_bucket)\n+{\n+\tuint32_t n, sz;\n+\n+\tn = 0;\n+\tif (wsz != 0 && (type & RTE_IPSEC_SATP_DIR_MASK) ==\n+\t\t\tRTE_IPSEC_SATP_DIR_IB)\n+\t\tn = replay_num_bucket(wsz);\n+\n+\tif (n > WINDOW_BUCKET_MAX)\n+\t\treturn -EINVAL;\n+\n+\t*nb_bucket = n;\n+\n+\tsz = rsn_size(n);\n+\tsz += sizeof(struct rte_ipsec_sa);\n+\treturn sz;\n+}\n+\n+void __rte_experimental\n+rte_ipsec_sa_fini(struct rte_ipsec_sa *sa)\n+{\n+\tmemset(sa, 0, sa->size);\n+}\n+\n+static uint64_t\n+fill_sa_type(const struct rte_ipsec_sa_prm *prm)\n+{\n+\tuint64_t tp;\n+\n+\ttp = 0;\n+\n+\tif (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)\n+\t\ttp |= RTE_IPSEC_SATP_PROTO_AH;\n+\telse if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP)\n+\t\ttp |= RTE_IPSEC_SATP_PROTO_ESP;\n+\n+\tif (prm->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)\n+\t\ttp |= RTE_IPSEC_SATP_DIR_OB;\n+\telse\n+\t\ttp |= RTE_IPSEC_SATP_DIR_IB;\n+\n+\tif (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {\n+\t\tif (prm->ipsec_xform.tunnel.type ==\n+\t\t\t\tRTE_SECURITY_IPSEC_TUNNEL_IPV4)\n+\t\t\ttp |= RTE_IPSEC_SATP_MODE_TUNLV4;\n+\t\telse\n+\t\t\ttp |= RTE_IPSEC_SATP_MODE_TUNLV6;\n+\n+\t\tif (prm->tun.next_proto == IPPROTO_IPIP)\n+\t\t\ttp |= RTE_IPSEC_SATP_IPV4;\n+\t\telse if (prm->tun.next_proto == IPPROTO_IPV6)\n+\t\t\ttp |= RTE_IPSEC_SATP_IPV4;\n+\t} else {\n+\t\ttp |= RTE_IPSEC_SATP_MODE_TRANS;\n+\t\tif (prm->trs.proto == IPPROTO_IPIP)\n+\t\t\ttp |= RTE_IPSEC_SATP_IPV4;\n+\t\telse if (prm->trs.proto == IPPROTO_IPV6)\n+\t\t\ttp |= RTE_IPSEC_SATP_IPV4;\n+\t}\n+\n+\treturn tp;\n+}\n+\n+static void\n+esp_inb_init(struct rte_ipsec_sa *sa)\n+{\n+\t/* these params may differ with new algorithms support */\n+\tsa->ctp.auth.offset = 0;\n+\tsa->ctp.auth.length = sa->icv_len - sa->sqh_len;\n+\tsa->ctp.cipher.offset = sizeof(struct esp_hdr) + sa->iv_len;\n+\tsa->ctp.cipher.length = sa->icv_len + sa->ctp.cipher.offset;\n+}\n+\n+static void\n+esp_inb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm)\n+{\n+\tsa->proto = prm->tun.next_proto;\n+\tesp_inb_init(sa);\n+}\n+\n+static void\n+esp_outb_init(struct rte_ipsec_sa *sa, uint32_t hlen)\n+{\n+\tsa->sqn.outb = 1;\n+\n+\t/* these params may differ with new algorithms support */\n+\tsa->ctp.auth.offset = hlen;\n+\tsa->ctp.auth.length = sizeof(struct esp_hdr) + sa->iv_len + sa->sqh_len;\n+\tif (sa->aad_len != 0) {\n+\t\tsa->ctp.cipher.offset = hlen + sizeof(struct esp_hdr) +\n+\t\t\tsa->iv_len;\n+\t\tsa->ctp.cipher.length = 0;\n+\t} else {\n+\t\tsa->ctp.cipher.offset = sa->hdr_len + sizeof(struct esp_hdr);\n+\t\tsa->ctp.cipher.length = sa->iv_len;\n+\t}\n+}\n+\n+static void\n+esp_outb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm)\n+{\n+\tsa->proto = prm->tun.next_proto;\n+\tsa->hdr_len = prm->tun.hdr_len;\n+\tsa->hdr_l3_off = prm->tun.hdr_l3_off;\n+\tmemcpy(sa->hdr, prm->tun.hdr, sa->hdr_len);\n+\n+\tesp_outb_init(sa, sa->hdr_len);\n+}\n+\n+static int\n+esp_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,\n+\tconst struct crypto_xform *cxf)\n+{\n+\tstatic const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |\n+\t\t\t\tRTE_IPSEC_SATP_MODE_MASK;\n+\n+\tif (cxf->aead != NULL) {\n+\t\t/* RFC 4106 */\n+\t\tif (cxf->aead->algo != RTE_CRYPTO_AEAD_AES_GCM)\n+\t\t\treturn -EINVAL;\n+\t\tsa->icv_len = cxf->aead->digest_length;\n+\t\tsa->iv_ofs = cxf->aead->iv.offset;\n+\t\tsa->iv_len = sizeof(uint64_t);\n+\t\tsa->pad_align = 4;\n+\t} else {\n+\t\tsa->icv_len = cxf->auth->digest_length;\n+\t\tsa->iv_ofs = cxf->cipher->iv.offset;\n+\t\tsa->sqh_len = IS_ESN(sa) ? sizeof(uint32_t) : 0;\n+\t\tif (cxf->cipher->algo == RTE_CRYPTO_CIPHER_NULL) {\n+\t\t\tsa->pad_align = 4;\n+\t\t\tsa->iv_len = 0;\n+\t\t} else if (cxf->cipher->algo == RTE_CRYPTO_CIPHER_AES_CBC) {\n+\t\t\tsa->pad_align = IPSEC_MAX_IV_SIZE;\n+\t\t\tsa->iv_len = IPSEC_MAX_IV_SIZE;\n+\t\t} else\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\tsa->udata = prm->userdata;\n+\tsa->spi = rte_cpu_to_be_32(prm->ipsec_xform.spi);\n+\tsa->salt = prm->ipsec_xform.salt;\n+\n+\tswitch (sa->type & msk) {\n+\tcase (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):\n+\tcase (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):\n+\t\tesp_inb_tun_init(sa, prm);\n+\t\tbreak;\n+\tcase (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):\n+\t\tesp_inb_init(sa);\n+\t\tbreak;\n+\tcase (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):\n+\tcase (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):\n+\t\tesp_outb_tun_init(sa, prm);\n+\t\tbreak;\n+\tcase (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):\n+\t\tesp_outb_init(sa, 0);\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int __rte_experimental\n+rte_ipsec_sa_size(const struct rte_ipsec_sa_prm *prm)\n+{\n+\tuint64_t type;\n+\tuint32_t nb;\n+\n+\tif (prm == NULL)\n+\t\treturn -EINVAL;\n+\n+\t/* determine SA type */\n+\ttype = fill_sa_type(prm);\n+\n+\t/* determine required size */\n+\treturn ipsec_sa_size(prm->replay_win_sz, type, &nb);\n+}\n+\n+int __rte_experimental\n+rte_ipsec_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,\n+\tuint32_t size)\n+{\n+\tint32_t rc, sz;\n+\tuint32_t nb;\n+\tuint64_t type;\n+\tstruct crypto_xform cxf;\n+\n+\tif (sa == NULL || prm == NULL)\n+\t\treturn -EINVAL;\n+\n+\t/* determine SA type */\n+\ttype = fill_sa_type(prm);\n+\n+\t/* determine required size */\n+\tsz = ipsec_sa_size(prm->replay_win_sz, type, &nb);\n+\tif (sz < 0)\n+\t\treturn sz;\n+\telse if (size < (uint32_t)sz)\n+\t\treturn -ENOSPC;\n+\n+\t/* only esp is supported right now */\n+\tif (prm->ipsec_xform.proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP)\n+\t\treturn -EINVAL;\n+\n+\tif (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&\n+\t\t\tprm->tun.hdr_len > sizeof(sa->hdr))\n+\t\treturn -EINVAL;\n+\n+\trc = fill_crypto_xform(&cxf, prm);\n+\tif (rc != 0)\n+\t\treturn rc;\n+\n+\tsa->type = type;\n+\tsa->size = sz;\n+\n+\t/* check for ESN flag */\n+\tsa->sqn_mask = (prm->ipsec_xform.options.esn == 0) ?\n+\t\tUINT32_MAX : UINT64_MAX;\n+\n+\trc = esp_sa_init(sa, prm, &cxf);\n+\tif (rc != 0)\n+\t\trte_ipsec_sa_fini(sa);\n+\n+\t/* fill replay window related fields */\n+\tif (nb != 0) {\n+\t\tsa->replay.win_sz = prm->replay_win_sz;\n+\t\tsa->replay.nb_bucket = nb;\n+\t\tsa->replay.bucket_index_mask = sa->replay.nb_bucket - 1;\n+\t\tsa->sqn.inb = (struct replay_sqn *)(sa + 1);\n+\t}\n+\n+\treturn sz;\n+}\ndiff --git a/lib/librte_ipsec/sa.h b/lib/librte_ipsec/sa.h\nnew file mode 100644\nindex 000000000..5d113891a\n--- /dev/null\n+++ b/lib/librte_ipsec/sa.h\n@@ -0,0 +1,77 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Intel Corporation\n+ */\n+\n+#ifndef _SA_H_\n+#define _SA_H_\n+\n+#define IPSEC_MAX_HDR_SIZE\t64\n+#define IPSEC_MAX_IV_SIZE\t16\n+#define IPSEC_MAX_IV_QWORD\t(IPSEC_MAX_IV_SIZE / sizeof(uint64_t))\n+\n+/* these definitions probably has to be in rte_crypto_sym.h */\n+union sym_op_ofslen {\n+\tuint64_t raw;\n+\tstruct {\n+\t\tuint32_t offset;\n+\t\tuint32_t length;\n+\t};\n+};\n+\n+union sym_op_data {\n+#ifdef __SIZEOF_INT128__\n+\t__uint128_t raw;\n+#endif\n+\tstruct {\n+\t\tuint8_t *va;\n+\t\trte_iova_t pa;\n+\t};\n+};\n+\n+struct replay_sqn {\n+\tuint64_t sqn;\n+\t__extension__ uint64_t window[0];\n+};\n+\n+struct rte_ipsec_sa {\n+\tuint64_t type;     /* type of given SA */\n+\tuint64_t udata;    /* user defined */\n+\tuint32_t size;     /* size of given sa object */\n+\tuint32_t spi;\n+\t/* sqn calculations related */\n+\tuint64_t sqn_mask;\n+\tstruct {\n+\t\tuint32_t win_sz;\n+\t\tuint16_t nb_bucket;\n+\t\tuint16_t bucket_index_mask;\n+\t} replay;\n+\t/* template for crypto op fields */\n+\tstruct {\n+\t\tunion sym_op_ofslen cipher;\n+\t\tunion sym_op_ofslen auth;\n+\t} ctp;\n+\tuint32_t salt;\n+\tuint8_t proto;    /* next proto */\n+\tuint8_t aad_len;\n+\tuint8_t hdr_len;\n+\tuint8_t hdr_l3_off;\n+\tuint8_t icv_len;\n+\tuint8_t sqh_len;\n+\tuint8_t iv_ofs; /* offset for algo-specific IV inside crypto op */\n+\tuint8_t iv_len;\n+\tuint8_t pad_align;\n+\n+\t/* template for tunnel header */\n+\tuint8_t hdr[IPSEC_MAX_HDR_SIZE];\n+\n+\t/*\n+\t * sqn and replay window\n+\t */\n+\tunion {\n+\t\tuint64_t outb;\n+\t\tstruct replay_sqn *inb;\n+\t} sqn;\n+\n+} __rte_cache_aligned;\n+\n+#endif /* _SA_H_ */\ndiff --git a/lib/meson.build b/lib/meson.build\nindex bb7f443f9..69684ef14 100644\n--- a/lib/meson.build\n+++ b/lib/meson.build\n@@ -22,6 +22,8 @@ libraries = [ 'compat', # just a header, used for versioning\n \t'kni', 'latencystats', 'lpm', 'member',\n \t'meter', 'power', 'pdump', 'rawdev',\n \t'reorder', 'sched', 'security', 'vhost',\n+\t#ipsec lib depends on crypto and security\n+\t'ipsec',\n \t# add pkt framework libs which use other libs from above\n \t'port', 'table', 'pipeline',\n \t# flow_classify lib depends on pkt framework table lib\ndiff --git a/mk/rte.app.mk b/mk/rte.app.mk\nindex 5699d979d..f4cd75252 100644\n--- a/mk/rte.app.mk\n+++ b/mk/rte.app.mk\n@@ -67,6 +67,8 @@ ifeq ($(CONFIG_RTE_LIBRTE_BPF_ELF),y)\n _LDLIBS-$(CONFIG_RTE_LIBRTE_BPF)            += -lelf\n endif\n \n+_LDLIBS-$(CONFIG_RTE_LIBRTE_IPSEC)            += -lrte_ipsec\n+\n _LDLIBS-y += --whole-archive\n \n _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile\n",
    "prefixes": [
        "4/9"
    ]
}