get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 64674,
    "url": "http://patches.dpdk.org/api/patches/64674/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1579012036-326214-4-git-send-email-vladimir.medvedkin@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": "<1579012036-326214-4-git-send-email-vladimir.medvedkin@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1579012036-326214-4-git-send-email-vladimir.medvedkin@intel.com",
    "date": "2020-01-14T14:27:14",
    "name": "[v4,3/5] examples/ipsec-secgw: integrate inbound SAD",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "c39fe25b1ae3df3397b6ec214bada68cf00a29e8",
    "submitter": {
        "id": 1216,
        "url": "http://patches.dpdk.org/api/people/1216/?format=api",
        "name": "Vladimir Medvedkin",
        "email": "vladimir.medvedkin@intel.com"
    },
    "delegate": {
        "id": 6690,
        "url": "http://patches.dpdk.org/api/users/6690/?format=api",
        "username": "akhil",
        "first_name": "akhil",
        "last_name": "goyal",
        "email": "gakhil@marvell.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1579012036-326214-4-git-send-email-vladimir.medvedkin@intel.com/mbox/",
    "series": [
        {
            "id": 8120,
            "url": "http://patches.dpdk.org/api/series/8120/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8120",
            "date": "2020-01-14T14:27:11",
            "name": "integrate librte_ipsec SAD into ipsec-secgw",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/8120/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/64674/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/64674/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 25143A04FF;\n\tTue, 14 Jan 2020 15:27:46 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 1398B1C1D3;\n\tTue, 14 Jan 2020 15:27:30 +0100 (CET)",
            "from mga07.intel.com (mga07.intel.com [134.134.136.100])\n by dpdk.org (Postfix) with ESMTP id BFAFD1C1BC\n for <dev@dpdk.org>; Tue, 14 Jan 2020 15:27:23 +0100 (CET)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n 14 Jan 2020 06:27:23 -0800",
            "from silpixa00400072.ir.intel.com ([10.237.222.213])\n by fmsmga002.fm.intel.com with ESMTP; 14 Jan 2020 06:27:21 -0800"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.69,433,1571727600\"; d=\"scan'208\";a=\"256316524\"",
        "From": "Vladimir Medvedkin <vladimir.medvedkin@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "konstantin.ananyev@intel.com,\n\takhil.goyal@nxp.com",
        "Date": "Tue, 14 Jan 2020 14:27:14 +0000",
        "Message-Id": "<1579012036-326214-4-git-send-email-vladimir.medvedkin@intel.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": [
            "<1579012036-326214-1-git-send-email-vladimir.medvedkin@intel.com>",
            "<1578920122-228017-1-git-send-email-vladimir.medvedkin@intel.com>"
        ],
        "References": [
            "<1579012036-326214-1-git-send-email-vladimir.medvedkin@intel.com>",
            "<1578920122-228017-1-git-send-email-vladimir.medvedkin@intel.com>"
        ],
        "Subject": "[dpdk-dev] [PATCH v4 3/5] examples/ipsec-secgw: integrate inbound\n\tSAD",
        "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 <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 <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Integrate ipsec SAD support into secgw app:\n\n1. Use SAD library for inbound SA lookup\n2. Changes in struct sa_ctx:\n  - sa array allocates dynamically depending on number of configured sa\n  - All SA's are kept one by one without using SPI2IDX\n3. SP's userdata now contain index of SA in sa_ctx instead of SPI\n4. Get rid of SPI2IDX macro\n\nSigned-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>\n---\n examples/ipsec-secgw/Makefile      |   1 +\n examples/ipsec-secgw/ipsec-secgw.c |   4 +-\n examples/ipsec-secgw/ipsec.h       |   3 +-\n examples/ipsec-secgw/meson.build   |   2 +-\n examples/ipsec-secgw/sa.c          | 182 +++++++++++++++++++++----------------\n examples/ipsec-secgw/sp4.c         |  24 +++--\n examples/ipsec-secgw/sp6.c         |  24 +++--\n 7 files changed, 139 insertions(+), 101 deletions(-)",
    "diff": "diff --git a/examples/ipsec-secgw/Makefile b/examples/ipsec-secgw/Makefile\nindex 851123b..8734b15 100644\n--- a/examples/ipsec-secgw/Makefile\n+++ b/examples/ipsec-secgw/Makefile\n@@ -12,6 +12,7 @@ SRCS-y += esp.c\n SRCS-y += sp4.c\n SRCS-y += sp6.c\n SRCS-y += sa.c\n+SRCS-y += sad.c\n SRCS-y += rt.c\n SRCS-y += ipsec_process.c\n SRCS-y += ipsec-secgw.c\ndiff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c\nindex 3b5aaf6..3e5f82e 100644\n--- a/examples/ipsec-secgw/ipsec-secgw.c\n+++ b/examples/ipsec-secgw/ipsec-secgw.c\n@@ -601,7 +601,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,\n \t\t\tcontinue;\n \t\t}\n \n-\t\tsa_idx = SPI2IDX(res);\n+\t\tsa_idx = res - 1;\n \t\tif (!inbound_sa_check(sa, m, sa_idx)) {\n \t\t\trte_pktmbuf_free(m);\n \t\t\tcontinue;\n@@ -688,7 +688,7 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,\n \tj = 0;\n \tfor (i = 0; i < ip->num; i++) {\n \t\tm = ip->pkts[i];\n-\t\tsa_idx = SPI2IDX(ip->res[i]);\n+\t\tsa_idx = ip->res[i] - 1;\n \t\tif (ip->res[i] == DISCARD)\n \t\t\trte_pktmbuf_free(m);\n \t\telse if (ip->res[i] == BYPASS)\ndiff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h\nindex 9ddb5d9..5988d59 100644\n--- a/examples/ipsec-secgw/ipsec.h\n+++ b/examples/ipsec-secgw/ipsec.h\n@@ -38,7 +38,6 @@\n #define DEFAULT_MAX_CATEGORIES\t1\n \n #define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */\n-#define SPI2IDX(spi) (spi & (IPSEC_SA_MAX_ENTRIES - 1))\n #define INVALID_SPI (0)\n \n #define DISCARD\tINVALID_SPI\n@@ -359,7 +358,7 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],\n  * or -ENOENT otherwise.\n  */\n int\n-sa_spi_present(uint32_t spi, int inbound);\n+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound);\n \n void\n sa_init(struct socket_ctx *ctx, int32_t socket_id);\ndiff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-secgw/meson.build\nindex 9ece345..6bd5b78 100644\n--- a/examples/ipsec-secgw/meson.build\n+++ b/examples/ipsec-secgw/meson.build\n@@ -10,5 +10,5 @@ deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec']\n allow_experimental_apis = true\n sources = files(\n \t'esp.c', 'ipsec.c', 'ipsec_process.c', 'ipsec-secgw.c',\n-\t'parser.c', 'rt.c', 'sa.c', 'sp4.c', 'sp6.c'\n+\t'parser.c', 'rt.c', 'sa.c', 'sad.c', 'sp4.c', 'sp6.c'\n )\ndiff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c\nindex 7f046e3..d10a6ec 100644\n--- a/examples/ipsec-secgw/sa.c\n+++ b/examples/ipsec-secgw/sa.c\n@@ -24,6 +24,7 @@\n #include \"ipsec.h\"\n #include \"esp.h\"\n #include \"parser.h\"\n+#include \"sad.h\"\n \n #define IPDEFTTL 64\n \n@@ -134,9 +135,11 @@ const struct supported_aead_algo aead_algos[] = {\n \n static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];\n static uint32_t nb_sa_out;\n+static struct ipsec_sa_cnt sa_out_cnt;\n \n static struct ipsec_sa sa_in[IPSEC_SA_MAX_ENTRIES];\n static uint32_t nb_sa_in;\n+static struct ipsec_sa_cnt sa_in_cnt;\n \n static const struct supported_cipher_algo *\n find_match_cipher_algo(const char *cipher_keyword)\n@@ -229,6 +232,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,\n \tstruct rte_ipsec_session *ips;\n \tuint32_t ti; /*token index*/\n \tuint32_t *ri /*rule index*/;\n+\tstruct ipsec_sa_cnt *sa_cnt;\n \tuint32_t cipher_algo_p = 0;\n \tuint32_t auth_algo_p = 0;\n \tuint32_t aead_algo_p = 0;\n@@ -241,6 +245,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,\n \n \tif (strcmp(tokens[0], \"in\") == 0) {\n \t\tri = &nb_sa_in;\n+\t\tsa_cnt = &sa_in_cnt;\n \n \t\tAPP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,\n \t\t\t\"too many sa rules, abort insertion\\n\");\n@@ -251,6 +256,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,\n \t\trule->direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;\n \t} else {\n \t\tri = &nb_sa_out;\n+\t\tsa_cnt = &sa_out_cnt;\n \n \t\tAPP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,\n \t\t\t\"too many sa rules, abort insertion\\n\");\n@@ -280,13 +286,17 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,\n \t\t\tif (status->status < 0)\n \t\t\t\treturn;\n \n-\t\t\tif (strcmp(tokens[ti], \"ipv4-tunnel\") == 0)\n+\t\t\tif (strcmp(tokens[ti], \"ipv4-tunnel\") == 0) {\n+\t\t\t\tsa_cnt->nb_v4++;\n \t\t\t\trule->flags = IP4_TUNNEL;\n-\t\t\telse if (strcmp(tokens[ti], \"ipv6-tunnel\") == 0)\n+\t\t\t} else if (strcmp(tokens[ti], \"ipv6-tunnel\") == 0) {\n+\t\t\t\tsa_cnt->nb_v6++;\n \t\t\t\trule->flags = IP6_TUNNEL;\n-\t\t\telse if (strcmp(tokens[ti], \"transport\") == 0)\n+\t\t\t} else if (strcmp(tokens[ti], \"transport\") == 0) {\n+\t\t\t\tsa_cnt->nb_v4++;\n+\t\t\t\tsa_cnt->nb_v6++;\n \t\t\t\trule->flags = TRANSPORT;\n-\t\t\telse {\n+\t\t\t} else {\n \t\t\t\tAPP_CHECK(0, status, \"unrecognized \"\n \t\t\t\t\t\"input \\\"%s\\\"\", tokens[ti]);\n \t\t\t\treturn;\n@@ -772,19 +782,21 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)\n \tprintf(\"\\n\");\n }\n \n+struct ipsec_xf {\n+\tstruct rte_crypto_sym_xform a;\n+\tstruct rte_crypto_sym_xform b;\n+};\n+\n struct sa_ctx {\n \tvoid *satbl; /* pointer to array of rte_ipsec_sa objects*/\n-\tstruct ipsec_sa sa[IPSEC_SA_MAX_ENTRIES];\n-\tunion {\n-\t\tstruct {\n-\t\t\tstruct rte_crypto_sym_xform a;\n-\t\t\tstruct rte_crypto_sym_xform b;\n-\t\t};\n-\t} xf[IPSEC_SA_MAX_ENTRIES];\n+\tstruct ipsec_sad sad;\n+\tstruct ipsec_xf *xf;\n+\tuint32_t nb_sa;\n+\tstruct ipsec_sa sa[];\n };\n \n static struct sa_ctx *\n-sa_create(const char *name, int32_t socket_id)\n+sa_create(const char *name, int32_t socket_id, uint32_t nb_sa)\n {\n \tchar s[PATH_MAX];\n \tstruct sa_ctx *sa_ctx;\n@@ -793,20 +805,31 @@ sa_create(const char *name, int32_t socket_id)\n \n \tsnprintf(s, sizeof(s), \"%s_%u\", name, socket_id);\n \n-\t/* Create SA array table */\n+\t/* Create SA context */\n \tprintf(\"Creating SA context with %u maximum entries on socket %d\\n\",\n-\t\t\tIPSEC_SA_MAX_ENTRIES, socket_id);\n+\t\t\tnb_sa, socket_id);\n \n-\tmz_size = sizeof(struct sa_ctx);\n+\tmz_size = sizeof(struct ipsec_xf) * nb_sa;\n \tmz = rte_memzone_reserve(s, mz_size, socket_id,\n \t\t\tRTE_MEMZONE_1GB | RTE_MEMZONE_SIZE_HINT_ONLY);\n \tif (mz == NULL) {\n-\t\tprintf(\"Failed to allocate SA DB memory\\n\");\n+\t\tprintf(\"Failed to allocate SA XFORM memory\\n\");\n \t\trte_errno = ENOMEM;\n \t\treturn NULL;\n \t}\n \n-\tsa_ctx = (struct sa_ctx *)mz->addr;\n+\tsa_ctx = rte_malloc(NULL, sizeof(struct sa_ctx) +\n+\t\tsizeof(struct ipsec_sa) * nb_sa, RTE_CACHE_LINE_SIZE);\n+\n+\tif (sa_ctx == NULL) {\n+\t\tprintf(\"Failed to allocate SA CTX memory\\n\");\n+\t\trte_errno = ENOMEM;\n+\t\trte_memzone_free(mz);\n+\t\treturn NULL;\n+\t}\n+\n+\tsa_ctx->xf = (struct ipsec_xf *)mz->addr;\n+\tsa_ctx->nb_sa = nb_sa;\n \n \treturn sa_ctx;\n }\n@@ -949,7 +972,7 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n \taad_length = (app_sa_prm.enable_esn != 0) ? sizeof(uint32_t) : 0;\n \n \tfor (i = 0; i < nb_entries; i++) {\n-\t\tidx = SPI2IDX(entries[i].spi);\n+\t\tidx = i;\n \t\tsa = &sa_ctx->sa[idx];\n \t\tif (sa->spi != 0) {\n \t\t\tprintf(\"Index %u already in use by SPI %u\\n\",\n@@ -957,6 +980,13 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n \t\t\treturn -EINVAL;\n \t\t}\n \t\t*sa = entries[i];\n+\n+\t\tif (inbound) {\n+\t\t\trc = ipsec_sad_add(&sa_ctx->sad, sa);\n+\t\t\tif (rc != 0)\n+\t\t\t\treturn rc;\n+\t\t}\n+\n \t\tsa->seq = 0;\n \t\tips = ipsec_get_primary_session(sa);\n \n@@ -1237,8 +1267,7 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)\n  * one per session.\n  */\n static int\n-ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,\n-\tuint32_t nb_ent, int32_t socket)\n+ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket)\n {\n \tint32_t rc, sz;\n \tuint32_t i, idx;\n@@ -1248,7 +1277,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,\n \tstruct rte_ipsec_sa_prm prm;\n \n \t/* determine SA size */\n-\tidx = SPI2IDX(ent[0].spi);\n+\tidx = 0;\n \tfill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL);\n \tsz = rte_ipsec_sa_size(&prm);\n \tif (sz < 0) {\n@@ -1271,7 +1300,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,\n \trc = 0;\n \tfor (i = 0; i != nb_ent && rc == 0; i++) {\n \n-\t\tidx = SPI2IDX(ent[i].spi);\n+\t\tidx = i;\n \n \t\tsa = (struct rte_ipsec_sa *)((uintptr_t)ctx->satbl + sz * i);\n \t\tlsa = ctx->sa + idx;\n@@ -1286,18 +1315,16 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,\n  * Walk through all SA rules to find an SA with given SPI\n  */\n int\n-sa_spi_present(uint32_t spi, int inbound)\n+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)\n {\n \tuint32_t i, num;\n \tconst struct ipsec_sa *sar;\n \n-\tif (inbound != 0) {\n-\t\tsar = sa_in;\n+\tsar = sa_ctx->sa;\n+\tif (inbound != 0)\n \t\tnum = nb_sa_in;\n-\t} else {\n-\t\tsar = sa_out;\n+\telse\n \t\tnum = nb_sa_out;\n-\t}\n \n \tfor (i = 0; i != num; i++) {\n \t\tif (sar[i].spi == spi)\n@@ -1326,16 +1353,21 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)\n \n \tif (nb_sa_in > 0) {\n \t\tname = \"sa_in\";\n-\t\tctx->sa_in = sa_create(name, socket_id);\n+\t\tctx->sa_in = sa_create(name, socket_id, nb_sa_in);\n \t\tif (ctx->sa_in == NULL)\n \t\t\trte_exit(EXIT_FAILURE, \"Error [%d] creating SA \"\n \t\t\t\t\"context %s in socket %d\\n\", rte_errno,\n \t\t\t\tname, socket_id);\n \n+\t\trc = ipsec_sad_create(name, &ctx->sa_in->sad, socket_id,\n+\t\t\t\t&sa_in_cnt);\n+\t\tif (rc != 0)\n+\t\t\trte_exit(EXIT_FAILURE, \"failed to init SAD\\n\");\n+\n \t\tsa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in, ctx);\n \n \t\tif (app_sa_prm.enable != 0) {\n-\t\t\trc = ipsec_satbl_init(ctx->sa_in, sa_in, nb_sa_in,\n+\t\t\trc = ipsec_satbl_init(ctx->sa_in, nb_sa_in,\n \t\t\t\tsocket_id);\n \t\t\tif (rc != 0)\n \t\t\t\trte_exit(EXIT_FAILURE,\n@@ -1346,7 +1378,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)\n \n \tif (nb_sa_out > 0) {\n \t\tname = \"sa_out\";\n-\t\tctx->sa_out = sa_create(name, socket_id);\n+\t\tctx->sa_out = sa_create(name, socket_id, nb_sa_out);\n \t\tif (ctx->sa_out == NULL)\n \t\t\trte_exit(EXIT_FAILURE, \"Error [%d] creating SA \"\n \t\t\t\t\"context %s in socket %d\\n\", rte_errno,\n@@ -1355,7 +1387,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)\n \t\tsa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx);\n \n \t\tif (app_sa_prm.enable != 0) {\n-\t\t\trc = ipsec_satbl_init(ctx->sa_out, sa_out, nb_sa_out,\n+\t\t\trc = ipsec_satbl_init(ctx->sa_out, nb_sa_out,\n \t\t\t\tsocket_id);\n \t\t\tif (rc != 0)\n \t\t\t\trte_exit(EXIT_FAILURE,\n@@ -1381,28 +1413,18 @@ inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx)\n \treturn 0;\n }\n \n-static inline void\n-single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,\n-\t\tvoid **sa_ret)\n+void\n+inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],\n+\t\tvoid *sa_arr[], uint16_t nb_pkts)\n {\n-\tstruct rte_esp_hdr *esp;\n+\tuint32_t i;\n \tstruct ip *ip;\n \tuint32_t *src4_addr;\n \tuint8_t *src6_addr;\n-\tstruct ipsec_sa *sa;\n \tvoid *result_sa;\n+\tstruct ipsec_sa *sa;\n \n-\t*sa_ret = NULL;\n-\n-\tip = rte_pktmbuf_mtod(pkt, struct ip *);\n-\tesp = rte_pktmbuf_mtod_offset(pkt, struct rte_esp_hdr *, pkt->l3_len);\n-\n-\tif (esp->spi == INVALID_SPI)\n-\t\treturn;\n-\n-\tresult_sa = sa = &sadb[SPI2IDX(rte_be_to_cpu_32(esp->spi))];\n-\tif (rte_be_to_cpu_32(esp->spi) != sa->spi)\n-\t\treturn;\n+\tsad_lookup(&sa_ctx->sad, pkts, sa_arr, nb_pkts);\n \n \t/*\n \t * Mark need for inline offload fallback on the LSB of SA pointer.\n@@ -1413,43 +1435,47 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,\n \t * pointer to prevent from unintentional use. Use ipsec_mask_saptr\n \t * to get valid struct pointer.\n \t */\n-\tif (MBUF_NO_SEC_OFFLOAD(pkt) && sa->fallback_sessions > 0) {\n-\t\tuintptr_t intsa = (uintptr_t)sa;\n-\t\tintsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG;\n-\t\tresult_sa = (void *)intsa;\n-\t}\n+\tfor (i = 0; i < nb_pkts; i++) {\n+\t\tif (sa_arr[i] == NULL)\n+\t\t\tcontinue;\n \n-\tswitch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {\n-\tcase IP4_TUNNEL:\n-\t\tsrc4_addr = RTE_PTR_ADD(ip, offsetof(struct ip, ip_src));\n-\t\tif ((ip->ip_v == IPVERSION) &&\n-\t\t\t\t(sa->src.ip.ip4 == *src4_addr) &&\n-\t\t\t\t(sa->dst.ip.ip4 == *(src4_addr + 1)))\n-\t\t\t*sa_ret = result_sa;\n-\t\tbreak;\n-\tcase IP6_TUNNEL:\n-\t\tsrc6_addr = RTE_PTR_ADD(ip, offsetof(struct ip6_hdr, ip6_src));\n-\t\tif ((ip->ip_v == IP6_VERSION) &&\n+\t\tresult_sa = sa = sa_arr[i];\n+\t\tif (MBUF_NO_SEC_OFFLOAD(pkts[i]) &&\n+\t\t\tsa->fallback_sessions > 0) {\n+\t\t\tuintptr_t intsa = (uintptr_t)sa;\n+\t\t\tintsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG;\n+\t\t\tresult_sa = (void *)intsa;\n+\t\t}\n+\n+\t\tip = rte_pktmbuf_mtod(pkts[i], struct ip *);\n+\t\tswitch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {\n+\t\tcase IP4_TUNNEL:\n+\t\t\tsrc4_addr = RTE_PTR_ADD(ip,\n+\t\t\t\toffsetof(struct ip, ip_src));\n+\t\t\tif ((ip->ip_v == IPVERSION) &&\n+\t\t\t\t\t(sa->src.ip.ip4 == *src4_addr) &&\n+\t\t\t\t\t(sa->dst.ip.ip4 == *(src4_addr + 1)))\n+\t\t\t\tsa_arr[i] = result_sa;\n+\t\t\telse\n+\t\t\t\tsa_arr[i] = NULL;\n+\t\t\tbreak;\n+\t\tcase IP6_TUNNEL:\n+\t\t\tsrc6_addr = RTE_PTR_ADD(ip,\n+\t\t\t\toffsetof(struct ip6_hdr, ip6_src));\n+\t\t\tif ((ip->ip_v == IP6_VERSION) &&\n \t\t\t\t!memcmp(&sa->src.ip.ip6.ip6, src6_addr, 16) &&\n \t\t\t\t!memcmp(&sa->dst.ip.ip6.ip6, src6_addr + 16, 16))\n-\t\t\t*sa_ret = result_sa;\n-\t\tbreak;\n-\tcase TRANSPORT:\n-\t\t*sa_ret = result_sa;\n+\t\t\t\tsa_arr[i] = result_sa;\n+\t\t\telse\n+\t\t\t\tsa_arr[i] = NULL;\n+\t\t\tbreak;\n+\t\tcase TRANSPORT:\n+\t\t\tsa_arr[i] = result_sa;\n+\t\t}\n \t}\n }\n \n void\n-inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],\n-\t\tvoid *sa[], uint16_t nb_pkts)\n-{\n-\tuint32_t i;\n-\n-\tfor (i = 0; i < nb_pkts; i++)\n-\t\tsingle_inbound_lookup(sa_ctx->sa, pkts[i], &sa[i]);\n-}\n-\n-void\n outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],\n \t\tvoid *sa[], uint16_t nb_pkts)\n {\ndiff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c\nindex 3871c6c..1dcec52 100644\n--- a/examples/ipsec-secgw/sp4.c\n+++ b/examples/ipsec-secgw/sp4.c\n@@ -493,10 +493,11 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,\n  * check that for each rule it's SPI has a correspondent entry in SAD\n  */\n static int\n-check_spi_value(int inbound)\n+check_spi_value(struct sa_ctx *sa_ctx, int inbound)\n {\n \tuint32_t i, num, spi;\n-\tconst struct acl4_rules *acr;\n+\tint32_t spi_idx;\n+\tstruct acl4_rules *acr;\n \n \tif (inbound != 0) {\n \t\tacr = acl4_rules_in;\n@@ -508,11 +509,16 @@ check_spi_value(int inbound)\n \n \tfor (i = 0; i != num; i++) {\n \t\tspi = acr[i].data.userdata;\n-\t\tif (spi != DISCARD && spi != BYPASS &&\n-\t\t\t\tsa_spi_present(spi, inbound) < 0) {\n-\t\t\tRTE_LOG(ERR, IPSEC, \"SPI %u is not present in SAD\\n\",\n-\t\t\t\tspi);\n-\t\t\treturn -ENOENT;\n+\t\tif (spi != DISCARD && spi != BYPASS) {\n+\t\t\tspi_idx = sa_spi_present(sa_ctx, spi, inbound);\n+\t\t\tif (spi_idx < 0) {\n+\t\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\t\"SPI %u is not present in SAD\\n\",\n+\t\t\t\t\tspi);\n+\t\t\t\treturn -ENOENT;\n+\t\t\t}\n+\t\t\t/* Update userdata with spi index */\n+\t\t\tacr[i].data.userdata = spi_idx + 1;\n \t\t}\n \t}\n \n@@ -535,11 +541,11 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id)\n \t\trte_exit(EXIT_FAILURE, \"Outbound SP DB for socket %u already \"\n \t\t\t\t\"initialized\\n\", socket_id);\n \n-\tif (check_spi_value(1) < 0)\n+\tif (check_spi_value(ctx->sa_in, 1) < 0)\n \t\trte_exit(EXIT_FAILURE,\n \t\t\t\"Inbound IPv4 SP DB has unmatched in SAD SPIs\\n\");\n \n-\tif (check_spi_value(0) < 0)\n+\tif (check_spi_value(ctx->sa_out, 0) < 0)\n \t\trte_exit(EXIT_FAILURE,\n \t\t\t\"Outbound IPv4 SP DB has unmatched in SAD SPIs\\n\");\n \ndiff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c\nindex d8be6b1..b489e15 100644\n--- a/examples/ipsec-secgw/sp6.c\n+++ b/examples/ipsec-secgw/sp6.c\n@@ -625,10 +625,11 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,\n  * check that for each rule it's SPI has a correspondent entry in SAD\n  */\n static int\n-check_spi_value(int inbound)\n+check_spi_value(struct sa_ctx *sa_ctx, int inbound)\n {\n \tuint32_t i, num, spi;\n-\tconst struct acl6_rules *acr;\n+\tint32_t spi_idx;\n+\tstruct acl6_rules *acr;\n \n \tif (inbound != 0) {\n \t\tacr = acl6_rules_in;\n@@ -640,11 +641,16 @@ check_spi_value(int inbound)\n \n \tfor (i = 0; i != num; i++) {\n \t\tspi = acr[i].data.userdata;\n-\t\tif (spi != DISCARD && spi != BYPASS &&\n-\t\t\t\tsa_spi_present(spi, inbound) < 0) {\n-\t\t\tRTE_LOG(ERR, IPSEC, \"SPI %u is not present in SAD\\n\",\n-\t\t\t\tspi);\n-\t\t\treturn -ENOENT;\n+\t\tif (spi != DISCARD && spi != BYPASS) {\n+\t\t\tspi_idx = sa_spi_present(sa_ctx, spi, inbound);\n+\t\t\tif (spi_idx < 0) {\n+\t\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\t\"SPI %u is not present in SAD\\n\",\n+\t\t\t\t\tspi);\n+\t\t\t\treturn -ENOENT;\n+\t\t\t}\n+\t\t\t/* Update userdata with spi index */\n+\t\t\tacr[i].data.userdata = spi_idx + 1;\n \t\t}\n \t}\n \n@@ -667,11 +673,11 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)\n \t\trte_exit(EXIT_FAILURE, \"Outbound IPv6 SP DB for socket %u \"\n \t\t\t\t\"already initialized\\n\", socket_id);\n \n-\tif (check_spi_value(1) < 0)\n+\tif (check_spi_value(ctx->sa_in, 1) < 0)\n \t\trte_exit(EXIT_FAILURE,\n \t\t\t\"Inbound IPv6 SP DB has unmatched in SAD SPIs\\n\");\n \n-\tif (check_spi_value(0) < 0)\n+\tif (check_spi_value(ctx->sa_out, 0) < 0)\n \t\trte_exit(EXIT_FAILURE,\n \t\t\t\"Outbound IPv6 SP DB has unmatched in SAD SPIs\\n\");\n \n",
    "prefixes": [
        "v4",
        "3/5"
    ]
}