get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 52861,
    "url": "http://patches.dpdk.org/api/patches/52861/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1555508563-2752-2-git-send-email-bernard.iremonger@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": "<1555508563-2752-2-git-send-email-bernard.iremonger@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1555508563-2752-2-git-send-email-bernard.iremonger@intel.com",
    "date": "2019-04-17T13:42:42",
    "name": "[v4,1/2] examples/ipsec-secgw: fix 1st packet dropped for inline crypto",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "5757eee742d85e887105af268b96831959b40065",
    "submitter": {
        "id": 91,
        "url": "http://patches.dpdk.org/api/people/91/?format=api",
        "name": "Iremonger, Bernard",
        "email": "bernard.iremonger@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/1555508563-2752-2-git-send-email-bernard.iremonger@intel.com/mbox/",
    "series": [
        {
            "id": 4120,
            "url": "http://patches.dpdk.org/api/series/4120/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=4120",
            "date": "2019-04-04T13:28:13",
            "name": "examples/ipsec-secgw: fix 1st pkt dropped",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/4120/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/52861/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/52861/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 E61EC1B642;\n\tWed, 17 Apr 2019 15:42:55 +0200 (CEST)",
            "from mga12.intel.com (mga12.intel.com [192.55.52.136])\n\tby dpdk.org (Postfix) with ESMTP id B3CD01B635;\n\tWed, 17 Apr 2019 15:42:52 +0200 (CEST)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n\tby fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t17 Apr 2019 06:42:52 -0700",
            "from sivswdev08.ir.intel.com (HELO localhost.localdomain)\n\t([10.237.217.47])\n\tby orsmga008.jf.intel.com with ESMTP; 17 Apr 2019 06:42:49 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.60,362,1549958400\"; d=\"scan'208\";a=\"135120989\"",
        "From": "Bernard Iremonger <bernard.iremonger@intel.com>",
        "To": "dev@dpdk.org,\n\tkonstantin.ananyev@intel.com,\n\takhil.goyal@nxp.com",
        "Cc": "Bernard Iremonger <bernard.iremonger@intel.com>,\n\tstable@dpdk.org",
        "Date": "Wed, 17 Apr 2019 14:42:42 +0100",
        "Message-Id": "<1555508563-2752-2-git-send-email-bernard.iremonger@intel.com>",
        "X-Mailer": "git-send-email 1.7.0.7",
        "In-Reply-To": "<1554384495-7936-1-git-send-email-bernard.iremonger@intel.com>",
        "References": "<1554384495-7936-1-git-send-email-bernard.iremonger@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v4 1/2] examples/ipsec-secgw: fix 1st packet\n\tdropped for inline crypto",
        "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": "Inline crypto installs a flow rule in the NIC. This flow\nrule must be installed before the first inbound packet is\nreceived.\n\nThe create_session() function installs the flow rule.\n\nRefactor ipsec-secgw.c, sa.c, ipsec.h and ipsec.c to create\nsessions at startup to fix the issue of the first packet\nbeing dropped for inline crypto.\n\nThe create_session() function is now called at initialisation in\nsa_add_rules() which is called from sa_init().\nThe return code for add_rules is checked.\nCalls to create_session() in other functions are dropped.\n\nAdd crypto_devid_fill() in ipsec-secgw.c\nAdd max_session_size() in ipsec-secgw.c\nAdd check_cryptodev_capability() in ipsec.c\nAdd check_cryptodev_aead_capability() in ipsec.c\nAdd create_sec_session() and create_crypto_session() in ipsec.c\n\nThe crypto_dev_fill() function has been added to find the\nenabled crypto devices.\n\nThe max_session_size() function has been added to calculate memory\nrequirements.\n\nThe check_cryptodev_capability() and check_cryptodev_aead_capability()\nfunctions have been added to check that the SA is supported by the\ncrypto device.\n\nThe create_session() function is refactored to use the\ncreate_sec_session() and create_crypto_session() functions.\n\nThe cryprodev_init() function has been refactored to drop calls to\nrte_mempool_create() and to drop calculation of memory requirements.\n\nThe main() function has been refactored to call crypto_devid_fill()\nand max_session_size() and to call session_pool_init() and\nsession_priv_pool_init().\nThe ports are started now before adding a flow rule in main().\nThe sa_init(), sp4_init(), sp6_init() and rt_init() functions are\nnow called after the ports have been started.\n\nFixes: ec17993a145a (\"examples/ipsec-secgw: support security offload\")\nFixes: d299106e8e31 (\"examples/ipsec-secgw: add IPsec sample application\")\nCc: stable@dpdk.org\n\nSigned-off-by: Bernard Iremonger <bernard.iremonger@intel.com>\nAcked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\n---\n examples/ipsec-secgw/ipsec-secgw.c   | 271 ++++++++--------\n examples/ipsec-secgw/ipsec.c         | 581 +++++++++++++++++++----------------\n examples/ipsec-secgw/ipsec.h         |  10 +-\n examples/ipsec-secgw/ipsec_process.c |  38 +--\n examples/ipsec-secgw/sa.c            |  42 ++-\n 5 files changed, 501 insertions(+), 441 deletions(-)",
    "diff": "diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c\nindex ffbd00b..cc8bb57 100644\n--- a/examples/ipsec-secgw/ipsec-secgw.c\n+++ b/examples/ipsec-secgw/ipsec-secgw.c\n@@ -182,6 +182,14 @@ struct lcore_params {\n \tuint8_t lcore_id;\n } __rte_cache_aligned;\n \n+/*\n+ * Number of enabled crypto devices\n+ * This number is needed when checking crypto device capabilities\n+ */\n+uint8_t crypto_dev_num;\n+/* array of crypto device ID's */\n+uint8_t crypto_devid[RTE_CRYPTO_MAX_DEVS];\n+\n static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS];\n \n static struct lcore_params *lcore_params;\n@@ -1623,13 +1631,27 @@ check_cryptodev_mask(uint8_t cdev_id)\n \treturn -1;\n }\n \n+static void\n+crypto_devid_fill(void)\n+{\n+\tuint32_t i, n;\n+\n+\tn = rte_cryptodev_count();\n+\n+\tfor (i = 0; i != n; i++) {\n+\t\tif (check_cryptodev_mask(i) == 0)\n+\t\t\tcrypto_devid[crypto_dev_num++] = i;\n+\t}\n+}\n+\n static int32_t\n cryptodevs_init(void)\n {\n \tstruct rte_cryptodev_config dev_conf;\n \tstruct rte_cryptodev_qp_conf qp_conf;\n \tuint16_t idx, max_nb_qps, qp, i;\n-\tint16_t cdev_id, port_id;\n+\tint16_t cdev_id;\n+\tuint32_t dev_max_sess;\n \tstruct rte_hash_parameters params = { 0 };\n \n \tparams.entries = CDEV_MAP_ENTRIES;\n@@ -1652,45 +1674,6 @@ cryptodevs_init(void)\n \n \tprintf(\"lcore/cryptodev/qp mappings:\\n\");\n \n-\tuint32_t max_sess_sz = 0, sess_sz;\n-\tfor (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) {\n-\t\tvoid *sec_ctx;\n-\n-\t\t/* Get crypto priv session size */\n-\t\tsess_sz = rte_cryptodev_sym_get_private_session_size(cdev_id);\n-\t\tif (sess_sz > max_sess_sz)\n-\t\t\tmax_sess_sz = sess_sz;\n-\n-\t\t/*\n-\t\t * If crypto device is security capable, need to check the\n-\t\t * size of security session as well.\n-\t\t */\n-\n-\t\t/* Get security context of the crypto device */\n-\t\tsec_ctx = rte_cryptodev_get_sec_ctx(cdev_id);\n-\t\tif (sec_ctx == NULL)\n-\t\t\tcontinue;\n-\n-\t\t/* Get size of security session */\n-\t\tsess_sz = rte_security_session_get_size(sec_ctx);\n-\t\tif (sess_sz > max_sess_sz)\n-\t\t\tmax_sess_sz = sess_sz;\n-\t}\n-\tRTE_ETH_FOREACH_DEV(port_id) {\n-\t\tvoid *sec_ctx;\n-\n-\t\tif ((enabled_port_mask & (1 << port_id)) == 0)\n-\t\t\tcontinue;\n-\n-\t\tsec_ctx = rte_eth_dev_get_sec_ctx(port_id);\n-\t\tif (sec_ctx == NULL)\n-\t\t\tcontinue;\n-\n-\t\tsess_sz = rte_security_session_get_size(sec_ctx);\n-\t\tif (sess_sz > max_sess_sz)\n-\t\t\tmax_sess_sz = sess_sz;\n-\t}\n-\n \tidx = 0;\n \tfor (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) {\n \t\tstruct rte_cryptodev_info cdev_info;\n@@ -1722,51 +1705,12 @@ cryptodevs_init(void)\n \t\tdev_conf.socket_id = rte_cryptodev_socket_id(cdev_id);\n \t\tdev_conf.nb_queue_pairs = qp;\n \n-\t\tuint32_t dev_max_sess = cdev_info.sym.max_nb_sessions;\n+\t\tdev_max_sess = cdev_info.sym.max_nb_sessions;\n \t\tif (dev_max_sess != 0 && dev_max_sess < CDEV_MP_NB_OBJS)\n \t\t\trte_exit(EXIT_FAILURE,\n \t\t\t\t\"Device does not support at least %u \"\n \t\t\t\t\"sessions\", CDEV_MP_NB_OBJS);\n \n-\t\tif (!socket_ctx[dev_conf.socket_id].session_pool) {\n-\t\t\tchar mp_name[RTE_MEMPOOL_NAMESIZE];\n-\t\t\tstruct rte_mempool *sess_mp;\n-\n-\t\t\tsnprintf(mp_name, RTE_MEMPOOL_NAMESIZE,\n-\t\t\t\t\t\"sess_mp_%u\", dev_conf.socket_id);\n-\t\t\tsess_mp = rte_cryptodev_sym_session_pool_create(\n-\t\t\t\t\tmp_name, CDEV_MP_NB_OBJS,\n-\t\t\t\t\t0, CDEV_MP_CACHE_SZ, 0,\n-\t\t\t\t\tdev_conf.socket_id);\n-\t\t\tsocket_ctx[dev_conf.socket_id].session_pool = sess_mp;\n-\t\t}\n-\n-\t\tif (!socket_ctx[dev_conf.socket_id].session_priv_pool) {\n-\t\t\tchar mp_name[RTE_MEMPOOL_NAMESIZE];\n-\t\t\tstruct rte_mempool *sess_mp;\n-\n-\t\t\tsnprintf(mp_name, RTE_MEMPOOL_NAMESIZE,\n-\t\t\t\t\t\"sess_mp_priv_%u\", dev_conf.socket_id);\n-\t\t\tsess_mp = rte_mempool_create(mp_name,\n-\t\t\t\t\tCDEV_MP_NB_OBJS,\n-\t\t\t\t\tmax_sess_sz,\n-\t\t\t\t\tCDEV_MP_CACHE_SZ,\n-\t\t\t\t\t0, NULL, NULL, NULL,\n-\t\t\t\t\tNULL, dev_conf.socket_id,\n-\t\t\t\t\t0);\n-\t\t\tsocket_ctx[dev_conf.socket_id].session_priv_pool =\n-\t\t\t\t\tsess_mp;\n-\t\t}\n-\n-\t\tif (!socket_ctx[dev_conf.socket_id].session_priv_pool ||\n-\t\t\t\t!socket_ctx[dev_conf.socket_id].session_pool)\n-\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\"Cannot create session pool on socket %d\\n\",\n-\t\t\t\tdev_conf.socket_id);\n-\t\telse\n-\t\t\tprintf(\"Allocated session pool on socket %d\\n\",\n-\t\t\t\t\tdev_conf.socket_id);\n-\n \t\tif (rte_cryptodev_configure(cdev_id, &dev_conf))\n \t\t\trte_panic(\"Failed to initialize cryptodev %u\\n\",\n \t\t\t\t\tcdev_id);\n@@ -1787,38 +1731,6 @@ cryptodevs_init(void)\n \t\t\t\t\tcdev_id);\n \t}\n \n-\t/* create session pools for eth devices that implement security */\n-\tRTE_ETH_FOREACH_DEV(port_id) {\n-\t\tif ((enabled_port_mask & (1 << port_id)) &&\n-\t\t\t\trte_eth_dev_get_sec_ctx(port_id)) {\n-\t\t\tint socket_id = rte_eth_dev_socket_id(port_id);\n-\n-\t\t\tif (!socket_ctx[socket_id].session_pool) {\n-\t\t\t\tchar mp_name[RTE_MEMPOOL_NAMESIZE];\n-\t\t\t\tstruct rte_mempool *sess_mp;\n-\n-\t\t\t\tsnprintf(mp_name, RTE_MEMPOOL_NAMESIZE,\n-\t\t\t\t\t\t\"sess_mp_%u\", socket_id);\n-\t\t\t\tsess_mp = rte_mempool_create(mp_name,\n-\t\t\t\t\t\t(CDEV_MP_NB_OBJS * 2),\n-\t\t\t\t\t\tmax_sess_sz,\n-\t\t\t\t\t\tCDEV_MP_CACHE_SZ,\n-\t\t\t\t\t\t0, NULL, NULL, NULL,\n-\t\t\t\t\t\tNULL, socket_id,\n-\t\t\t\t\t\t0);\n-\t\t\t\tif (sess_mp == NULL)\n-\t\t\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\t\t\"Cannot create session pool \"\n-\t\t\t\t\t\t\"on socket %d\\n\", socket_id);\n-\t\t\t\telse\n-\t\t\t\t\tprintf(\"Allocated session pool \"\n-\t\t\t\t\t\t\"on socket %d\\n\", socket_id);\n-\t\t\t\tsocket_ctx[socket_id].session_pool = sess_mp;\n-\t\t\t}\n-\t\t}\n-\t}\n-\n-\n \tprintf(\"\\n\");\n \n \treturn 0;\n@@ -1984,6 +1896,98 @@ port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads)\n \tprintf(\"\\n\");\n }\n \n+static size_t\n+max_session_size(void)\n+{\n+\tsize_t max_sz, sz;\n+\tvoid *sec_ctx;\n+\tint16_t cdev_id, port_id, n;\n+\n+\tmax_sz = 0;\n+\tn =  rte_cryptodev_count();\n+\tfor (cdev_id = 0; cdev_id != n; cdev_id++) {\n+\t\tsz = rte_cryptodev_sym_get_private_session_size(cdev_id);\n+\t\tif (sz > max_sz)\n+\t\t\tmax_sz = sz;\n+\t\t/*\n+\t\t * If crypto device is security capable, need to check the\n+\t\t * size of security session as well.\n+\t\t */\n+\n+\t\t/* Get security context of the crypto device */\n+\t\tsec_ctx = rte_cryptodev_get_sec_ctx(cdev_id);\n+\t\tif (sec_ctx == NULL)\n+\t\t\tcontinue;\n+\n+\t\t/* Get size of security session */\n+\t\tsz = rte_security_session_get_size(sec_ctx);\n+\t\tif (sz > max_sz)\n+\t\t\tmax_sz = sz;\n+\t}\n+\n+\tRTE_ETH_FOREACH_DEV(port_id) {\n+\t\tif ((enabled_port_mask & (1 << port_id)) == 0)\n+\t\t\tcontinue;\n+\n+\t\tsec_ctx = rte_eth_dev_get_sec_ctx(port_id);\n+\t\tif (sec_ctx == NULL)\n+\t\t\tcontinue;\n+\n+\t\tsz = rte_security_session_get_size(sec_ctx);\n+\t\tif (sz > max_sz)\n+\t\t\tmax_sz = sz;\n+\t}\n+\n+\treturn max_sz;\n+}\n+\n+static void\n+session_pool_init(struct socket_ctx *ctx, int32_t socket_id, size_t sess_sz)\n+{\n+\tchar mp_name[RTE_MEMPOOL_NAMESIZE];\n+\tstruct rte_mempool *sess_mp;\n+\n+\tsnprintf(mp_name, RTE_MEMPOOL_NAMESIZE,\n+\t\t\t\"sess_mp_%u\", socket_id);\n+\tsess_mp = rte_cryptodev_sym_session_pool_create(\n+\t\t\tmp_name, CDEV_MP_NB_OBJS,\n+\t\t\tsess_sz, CDEV_MP_CACHE_SZ, 0,\n+\t\t\tsocket_id);\n+\tctx->session_pool = sess_mp;\n+\n+\tif (ctx->session_pool == NULL)\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"Cannot init session pool on socket %d\\n\", socket_id);\n+\telse\n+\t\tprintf(\"Allocated session pool on socket %d\\n\",\tsocket_id);\n+}\n+\n+static void\n+session_priv_pool_init(struct socket_ctx *ctx, int32_t socket_id,\n+\tsize_t sess_sz)\n+{\n+\tchar mp_name[RTE_MEMPOOL_NAMESIZE];\n+\tstruct rte_mempool *sess_mp;\n+\n+\tsnprintf(mp_name, RTE_MEMPOOL_NAMESIZE,\n+\t\t\t\"sess_mp_priv_%u\", socket_id);\n+\tsess_mp = rte_mempool_create(mp_name,\n+\t\t\tCDEV_MP_NB_OBJS,\n+\t\t\tsess_sz,\n+\t\t\tCDEV_MP_CACHE_SZ,\n+\t\t\t0, NULL, NULL, NULL,\n+\t\t\tNULL, socket_id,\n+\t\t\t0);\n+\tctx->session_priv_pool = sess_mp;\n+\tif (ctx->session_priv_pool == NULL)\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"Cannot init session priv pool on socket %d\\n\",\n+\t\t\tsocket_id);\n+\telse\n+\t\tprintf(\"Allocated session priv pool on socket %d\\n\",\n+\t\t\tsocket_id);\n+}\n+\n static void\n pool_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t nb_mbuf)\n {\n@@ -2064,9 +2068,11 @@ main(int32_t argc, char **argv)\n {\n \tint32_t ret;\n \tuint32_t lcore_id;\n+\tuint32_t i;\n \tuint8_t socket_id;\n \tuint16_t portid;\n \tuint64_t req_rx_offloads, req_tx_offloads;\n+\tsize_t sess_sz;\n \n \t/* init EAL */\n \tret = rte_eal_init(argc, argv);\n@@ -2094,7 +2100,10 @@ main(int32_t argc, char **argv)\n \n \tnb_lcores = rte_lcore_count();\n \n-\t/* Replicate each context per socket */\n+\tcrypto_devid_fill();\n+\n+\tsess_sz = max_session_size();\n+\n \tfor (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n \t\tif (rte_lcore_is_enabled(lcore_id) == 0)\n \t\t\tcontinue;\n@@ -2104,20 +2113,17 @@ main(int32_t argc, char **argv)\n \t\telse\n \t\t\tsocket_id = 0;\n \n+\t\t/* mbuf_pool is initialised by the pool_init() function*/\n \t\tif (socket_ctx[socket_id].mbuf_pool)\n \t\t\tcontinue;\n \n-\t\t/* initilaze SPD */\n-\t\tsp4_init(&socket_ctx[socket_id], socket_id);\n-\n-\t\tsp6_init(&socket_ctx[socket_id], socket_id);\n-\n-\t\t/* initilaze SAD */\n-\t\tsa_init(&socket_ctx[socket_id], socket_id);\n-\n-\t\trt_init(&socket_ctx[socket_id], socket_id);\n-\n \t\tpool_init(&socket_ctx[socket_id], socket_id, NB_MBUF);\n+\t\tsession_pool_init(&socket_ctx[socket_id], socket_id, sess_sz);\n+\t\tsession_priv_pool_init(&socket_ctx[socket_id], socket_id,\n+\t\t\tsess_sz);\n+\n+\t\tif (!numa_on)\n+\t\t\tbreak;\n \t}\n \n \tRTE_ETH_FOREACH_DEV(portid) {\n@@ -2135,7 +2141,11 @@ main(int32_t argc, char **argv)\n \t\tif ((enabled_port_mask & (1 << portid)) == 0)\n \t\t\tcontinue;\n \n-\t\t/* Start device */\n+\t\t/*\n+\t\t * Start device\n+\t\t * note: device must be started before a flow rule\n+\t\t * can be installed.\n+\t\t */\n \t\tret = rte_eth_dev_start(portid);\n \t\tif (ret < 0)\n \t\t\trte_exit(EXIT_FAILURE, \"rte_eth_dev_start: \"\n@@ -2153,6 +2163,19 @@ main(int32_t argc, char **argv)\n \t\t\tRTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL);\n \t}\n \n+\t/* Replicate each context per socket */\n+\tfor (i = 0; i < NB_SOCKETS && i < rte_socket_count(); i++) {\n+\t\tsocket_id = rte_socket_id_by_idx(i);\n+\t\tif ((socket_ctx[socket_id].mbuf_pool != NULL) &&\n+\t\t\t(socket_ctx[socket_id].sa_in == NULL) &&\n+\t\t\t(socket_ctx[socket_id].sa_out == NULL)) {\n+\t\t\tsa_init(&socket_ctx[socket_id], socket_id);\n+\t\t\tsp4_init(&socket_ctx[socket_id], socket_id);\n+\t\t\tsp6_init(&socket_ctx[socket_id], socket_id);\n+\t\t\trt_init(&socket_ctx[socket_id], socket_id);\n+\t\t}\n+\t}\n+\n \tcheck_all_ports_link_status(enabled_port_mask);\n \n \t/* launch per-lcore init on every lcore */\ndiff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c\nindex 4352cb8..83080f7 100644\n--- a/examples/ipsec-secgw/ipsec.c\n+++ b/examples/ipsec-secgw/ipsec.c\n@@ -39,42 +39,17 @@ set_ipsec_conf(struct ipsec_sa *sa, struct rte_security_ipsec_xform *ipsec)\n \tipsec->esn_soft_limit = IPSEC_OFFLOAD_ESN_SOFTLIMIT;\n }\n \n-int\n-create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)\n+static int\n+create_sec_session(struct ipsec_sa *sa, struct rte_mempool *pool)\n {\n-\tstruct rte_cryptodev_info cdev_info;\n-\tunsigned long cdev_id_qp = 0;\n+\tconst struct rte_security_capability *sec_cap;\n+\tstruct rte_security_ctx *ctx;\n \tint32_t ret = 0;\n-\tstruct cdev_key key = { 0 };\n-\n-\tkey.lcore_id = (uint8_t)rte_lcore_id();\n-\n-\tkey.cipher_algo = (uint8_t)sa->cipher_algo;\n-\tkey.auth_algo = (uint8_t)sa->auth_algo;\n-\tkey.aead_algo = (uint8_t)sa->aead_algo;\n-\n-\tif (sa->type == RTE_SECURITY_ACTION_TYPE_NONE) {\n-\t\tret = rte_hash_lookup_data(ipsec_ctx->cdev_map, &key,\n-\t\t\t\t(void **)&cdev_id_qp);\n-\t\tif (ret < 0) {\n-\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\"No cryptodev: core %u, cipher_algo %u, \"\n-\t\t\t\t\"auth_algo %u, aead_algo %u\\n\",\n-\t\t\t\tkey.lcore_id,\n-\t\t\t\tkey.cipher_algo,\n-\t\t\t\tkey.auth_algo,\n-\t\t\t\tkey.aead_algo);\n-\t\t\treturn -1;\n-\t\t}\n-\t}\n \n-\tRTE_LOG_DP(DEBUG, IPSEC, \"Create session for SA spi %u on cryptodev \"\n-\t\t\t\"%u qp %u\\n\", sa->spi,\n-\t\t\tipsec_ctx->tbl[cdev_id_qp].id,\n-\t\t\tipsec_ctx->tbl[cdev_id_qp].qp);\n+\tif ((sa == NULL) || (pool == NULL))\n+\t\treturn -EINVAL;\n \n-\tif (sa->type != RTE_SECURITY_ACTION_TYPE_NONE) {\n-\t\tstruct rte_security_session_conf sess_conf = {\n+\tstruct rte_security_session_conf sess_conf = {\n \t\t\t.action_type = sa->type,\n \t\t\t.protocol = RTE_SECURITY_PROTOCOL_IPSEC,\n \t\t\t{.ipsec = {\n@@ -90,247 +65,340 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)\n \t\t\t} },\n \t\t\t.crypto_xform = sa->xforms,\n \t\t\t.userdata = NULL,\n-\n \t\t};\n \n-\t\tif (sa->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) {\n-\t\t\tstruct rte_security_ctx *ctx = (struct rte_security_ctx *)\n-\t\t\t\t\t\t\trte_cryptodev_get_sec_ctx(\n-\t\t\t\t\t\t\tipsec_ctx->tbl[cdev_id_qp].id);\n-\n-\t\t\t/* Set IPsec parameters in conf */\n-\t\t\tset_ipsec_conf(sa, &(sess_conf.ipsec));\n-\n-\t\t\tsa->sec_session = rte_security_session_create(ctx,\n-\t\t\t\t\t&sess_conf, ipsec_ctx->session_pool);\n-\t\t\tif (sa->sec_session == NULL) {\n-\t\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\"SEC Session init failed: err: %d\\n\", ret);\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\t\t} else if (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {\n-\t\t\tstruct rte_flow_error err;\n-\t\t\tstruct rte_security_ctx *ctx = (struct rte_security_ctx *)\n-\t\t\t\t\t\t\trte_eth_dev_get_sec_ctx(\n-\t\t\t\t\t\t\tsa->portid);\n-\t\t\tconst struct rte_security_capability *sec_cap;\n-\t\t\tint ret = 0;\n-\n-\t\t\tsa->sec_session = rte_security_session_create(ctx,\n-\t\t\t\t\t&sess_conf, ipsec_ctx->session_pool);\n-\t\t\tif (sa->sec_session == NULL) {\n-\t\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\"SEC Session init failed: err: %d\\n\", ret);\n-\t\t\t\treturn -1;\n-\t\t\t}\n+\tif (sa->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) {\n+\t\tctx = (struct rte_security_ctx *)\n+\t\t\t\trte_eth_dev_get_sec_ctx(sa->portid);\n \n-\t\t\tsec_cap = rte_security_capabilities_get(ctx);\n+\t\t/* Set IPsec parameters in conf */\n+\t\tset_ipsec_conf(sa, &(sess_conf.ipsec));\n \n-\t\t\t/* iterate until ESP tunnel*/\n-\t\t\twhile (sec_cap->action !=\n-\t\t\t\t\tRTE_SECURITY_ACTION_TYPE_NONE) {\n+\t\tsa->sec_session = rte_security_session_create(ctx,\n+\t\t\t\t&sess_conf, pool);\n+\t\tif (sa->sec_session == NULL) {\n+\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\"SEC Session init failed: err: %d\\n\",\n+\t\t\t\tret);\n+\t\t\treturn -1;\n+\t\t}\n+\t} else if (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {\n+\t\tstruct rte_flow_error err;\n+\t\tctx = (struct rte_security_ctx *)\n+\t\t\t\trte_eth_dev_get_sec_ctx(sa->portid);\n+\t\tsa->sec_session = rte_security_session_create(ctx,\n+\t\t\t\t&sess_conf, pool);\n+\t\tif (sa->sec_session == NULL) {\n+\t\t\tRTE_LOG(ERR, IPSEC, \"SEC Session init failed\\n\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t\t\t\tif (sec_cap->action == sa->type &&\n-\t\t\t\t    sec_cap->protocol ==\n-\t\t\t\t\tRTE_SECURITY_PROTOCOL_IPSEC &&\n-\t\t\t\t    sec_cap->ipsec.mode ==\n-\t\t\t\t\tRTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&\n-\t\t\t\t    sec_cap->ipsec.direction == sa->direction)\n-\t\t\t\t\tbreak;\n-\t\t\t\tsec_cap++;\n-\t\t\t}\n+\t\tsec_cap = rte_security_capabilities_get(ctx);\n+\n+\t\t/* iterate until ESP tunnel*/\n+\t\twhile (sec_cap->action != RTE_SECURITY_ACTION_TYPE_NONE) {\n+\t\t\tif (sec_cap->action == sa->type &&\n+\t\t\t\tsec_cap->protocol ==\n+\t\t\t\tRTE_SECURITY_PROTOCOL_IPSEC &&\n+\t\t\t\tsec_cap->ipsec.mode ==\n+\t\t\t\tRTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&\n+\t\t\t\tsec_cap->ipsec.direction == sa->direction)\n+\t\t\t\tbreak;\n+\t\t\tsec_cap++;\n+\t\t}\n \n-\t\t\tif (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) {\n-\t\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\tif (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) {\n+\t\t\tRTE_LOG(ERR, IPSEC,\n \t\t\t\t\"No suitable security capability found\\n\");\n \t\t\t\treturn -1;\n-\t\t\t}\n+\t\t}\n \n-\t\t\tsa->ol_flags = sec_cap->ol_flags;\n-\t\t\tsa->security_ctx = ctx;\n-\t\t\tsa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;\n-\n-\t\t\tsa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;\n-\t\t\tsa->pattern[1].mask = &rte_flow_item_ipv4_mask;\n-\t\t\tif (sa->flags & IP6_TUNNEL) {\n-\t\t\t\tsa->pattern[1].spec = &sa->ipv6_spec;\n-\t\t\t\tmemcpy(sa->ipv6_spec.hdr.dst_addr,\n-\t\t\t\t\tsa->dst.ip.ip6.ip6_b, 16);\n-\t\t\t\tmemcpy(sa->ipv6_spec.hdr.src_addr,\n-\t\t\t\t       sa->src.ip.ip6.ip6_b, 16);\n-\t\t\t} else {\n-\t\t\t\tsa->pattern[1].spec = &sa->ipv4_spec;\n-\t\t\t\tsa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;\n-\t\t\t\tsa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;\n-\t\t\t}\n+\t\tsa->ol_flags = sec_cap->ol_flags;\n+\t\tsa->security_ctx = ctx;\n+\t\tsa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;\n+\n+\t\tsa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;\n+\t\tsa->pattern[1].mask = &rte_flow_item_ipv4_mask;\n+\t\tif (sa->flags & IP6_TUNNEL) {\n+\t\t\tsa->pattern[1].spec = &sa->ipv6_spec;\n+\t\t\tmemcpy(sa->ipv6_spec.hdr.dst_addr,\n+\t\t\t\tsa->dst.ip.ip6.ip6_b, 16);\n+\t\t\tmemcpy(sa->ipv6_spec.hdr.src_addr,\n+\t\t\t       sa->src.ip.ip6.ip6_b, 16);\n+\t\t} else {\n+\t\t\tsa->pattern[1].spec = &sa->ipv4_spec;\n+\t\t\tsa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;\n+\t\t\tsa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;\n+\t\t}\n \n-\t\t\tsa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;\n-\t\t\tsa->pattern[2].spec = &sa->esp_spec;\n-\t\t\tsa->pattern[2].mask = &rte_flow_item_esp_mask;\n-\t\t\tsa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);\n+\t\tsa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;\n+\t\tsa->pattern[2].spec = &sa->esp_spec;\n+\t\tsa->pattern[2].mask = &rte_flow_item_esp_mask;\n+\t\tsa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);\n \n-\t\t\tsa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;\n+\t\tsa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;\n \n-\t\t\tsa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;\n-\t\t\tsa->action[0].conf = sa->sec_session;\n+\t\tsa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;\n+\t\tsa->action[0].conf = sa->sec_session;\n \n-\t\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_END;\n+\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_END;\n \n-\t\t\tsa->attr.egress = (sa->direction ==\n+\t\tsa->attr.egress = (sa->direction ==\n \t\t\t\t\tRTE_SECURITY_IPSEC_SA_DIR_EGRESS);\n-\t\t\tsa->attr.ingress = (sa->direction ==\n+\t\tsa->attr.ingress = (sa->direction ==\n \t\t\t\t\tRTE_SECURITY_IPSEC_SA_DIR_INGRESS);\n-\t\t\tif (sa->attr.ingress) {\n-\t\t\t\tuint8_t rss_key[40];\n-\t\t\t\tstruct rte_eth_rss_conf rss_conf = {\n-\t\t\t\t\t.rss_key = rss_key,\n-\t\t\t\t\t.rss_key_len = 40,\n-\t\t\t\t};\n-\t\t\t\tstruct rte_eth_dev *eth_dev;\n-\t\t\t\tuint16_t queue[RTE_MAX_QUEUES_PER_PORT];\n-\t\t\t\tstruct rte_flow_action_rss action_rss;\n-\t\t\t\tunsigned int i;\n-\t\t\t\tunsigned int j;\n-\n-\t\t\t\tsa->action[2].type = RTE_FLOW_ACTION_TYPE_END;\n-\t\t\t\t/* Try RSS. */\n-\t\t\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_RSS;\n-\t\t\t\tsa->action[1].conf = &action_rss;\n-\t\t\t\teth_dev = ctx->device;\n-\t\t\t\trte_eth_dev_rss_hash_conf_get(sa->portid,\n-\t\t\t\t\t\t\t      &rss_conf);\n-\t\t\t\tfor (i = 0, j = 0;\n-\t\t\t\t     i < eth_dev->data->nb_rx_queues; ++i)\n-\t\t\t\t\tif (eth_dev->data->rx_queues[i])\n-\t\t\t\t\t\tqueue[j++] = i;\n-\t\t\t\taction_rss = (struct rte_flow_action_rss){\n-\t\t\t\t\t.types = rss_conf.rss_hf,\n-\t\t\t\t\t.key_len = rss_conf.rss_key_len,\n-\t\t\t\t\t.queue_num = j,\n-\t\t\t\t\t.key = rss_key,\n-\t\t\t\t\t.queue = queue,\n-\t\t\t\t};\n-\t\t\t\tret = rte_flow_validate(sa->portid, &sa->attr,\n-\t\t\t\t\t\t\tsa->pattern, sa->action,\n-\t\t\t\t\t\t\t&err);\n-\t\t\t\tif (!ret)\n-\t\t\t\t\tgoto flow_create;\n-\t\t\t\t/* Try Queue. */\n-\t\t\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_QUEUE;\n-\t\t\t\tsa->action[1].conf =\n-\t\t\t\t\t&(struct rte_flow_action_queue){\n-\t\t\t\t\t.index = 0,\n-\t\t\t\t};\n-\t\t\t\tret = rte_flow_validate(sa->portid, &sa->attr,\n-\t\t\t\t\t\t\tsa->pattern, sa->action,\n-\t\t\t\t\t\t\t&err);\n-\t\t\t\t/* Try End. */\n-\t\t\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_END;\n-\t\t\t\tsa->action[1].conf = NULL;\n-\t\t\t\tret = rte_flow_validate(sa->portid, &sa->attr,\n+\t\tif (sa->attr.ingress) {\n+\t\t\tuint8_t rss_key[40];\n+\t\t\tstruct rte_eth_rss_conf rss_conf = {\n+\t\t\t\t.rss_key = rss_key,\n+\t\t\t\t.rss_key_len = 40,\n+\t\t\t};\n+\t\t\tstruct rte_eth_dev *eth_dev;\n+\t\t\tuint16_t queue[RTE_MAX_QUEUES_PER_PORT];\n+\t\t\tstruct rte_flow_action_rss action_rss;\n+\t\t\tunsigned int i;\n+\t\t\tunsigned int j;\n+\n+\t\t\tsa->action[2].type = RTE_FLOW_ACTION_TYPE_END;\n+\t\t\t/* Try RSS. */\n+\t\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_RSS;\n+\t\t\tsa->action[1].conf = &action_rss;\n+\t\t\teth_dev = ctx->device;\n+\t\t\trte_eth_dev_rss_hash_conf_get(sa->portid,\n+\t\t\t\t\t\t&rss_conf);\n+\t\t\tfor (i = 0, j = 0;\n+\t\t\t     i < eth_dev->data->nb_rx_queues; ++i)\n+\t\t\t\tif (eth_dev->data->rx_queues[i])\n+\t\t\t\t\tqueue[j++] = i;\n+\t\t\taction_rss = (struct rte_flow_action_rss){\n+\t\t\t\t.types = rss_conf.rss_hf,\n+\t\t\t\t.key_len = rss_conf.rss_key_len,\n+\t\t\t\t.queue_num = j,\n+\t\t\t\t.key = rss_key,\n+\t\t\t\t.queue = queue,\n+\t\t\t};\n+\t\t\tret = rte_flow_validate(sa->portid, &sa->attr,\n+\t\t\t\t\t\tsa->pattern, sa->action,\n+\t\t\t\t\t\t&err);\n+\t\t\tif (!ret)\n+\t\t\t\tgoto flow_create;\n+\t\t\t/* Try Queue. */\n+\t\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_QUEUE;\n+\t\t\tsa->action[1].conf =\n+\t\t\t\t&(struct rte_flow_action_queue){\n+\t\t\t\t.index = 0,\n+\t\t\t};\n+\t\t\tret = rte_flow_validate(sa->portid, &sa->attr,\n+\t\t\t\t\t\tsa->pattern, sa->action,\n+\t\t\t\t\t\t&err);\n+\t\t\t/* Try End. */\n+\t\t\tsa->action[1].type = RTE_FLOW_ACTION_TYPE_END;\n+\t\t\tsa->action[1].conf = NULL;\n+\t\t\tret = rte_flow_validate(sa->portid, &sa->attr,\n \t\t\t\t\t\t\tsa->pattern, sa->action,\n \t\t\t\t\t\t\t&err);\n-\t\t\t\tif (ret)\n-\t\t\t\t\tgoto flow_create_failure;\n-\t\t\t} else if (sa->attr.egress &&\n-\t\t\t\t   (sa->ol_flags &\n-\t\t\t\t    RTE_SECURITY_TX_HW_TRAILER_OFFLOAD)) {\n-\t\t\t\tsa->action[1].type =\n-\t\t\t\t\tRTE_FLOW_ACTION_TYPE_PASSTHRU;\n-\t\t\t\tsa->action[2].type =\n-\t\t\t\t\tRTE_FLOW_ACTION_TYPE_END;\n-\t\t\t}\n+\t\t\tif (ret)\n+\t\t\t\tgoto flow_create_failure;\n+\t\t} else if (sa->attr.egress &&\n+\t\t\t\t(sa->ol_flags &\n+\t\t\t\tRTE_SECURITY_TX_HW_TRAILER_OFFLOAD)) {\n+\t\t\tsa->action[1].type =\n+\t\t\t\tRTE_FLOW_ACTION_TYPE_PASSTHRU;\n+\t\t\tsa->action[2].type =\n+\t\t\t\tRTE_FLOW_ACTION_TYPE_END;\n+\t\t}\n flow_create:\n-\t\t\tsa->flow = rte_flow_create(sa->portid,\n-\t\t\t\t&sa->attr, sa->pattern, sa->action, &err);\n-\t\t\tif (sa->flow == NULL) {\n+\t\tsa->flow = rte_flow_create(sa->portid,\n+\t\t\t&sa->attr, sa->pattern, sa->action, &err);\n+\t\tif (sa->flow == NULL) {\n flow_create_failure:\n-\t\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\t\"Failed to create ipsec flow msg: %s\\n\",\n-\t\t\t\t\terr.message);\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\t\t} else if (sa->type ==\n-\t\t\t\tRTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) {\n-\t\t\tstruct rte_security_ctx *ctx =\n-\t\t\t\t\t(struct rte_security_ctx *)\n-\t\t\t\t\trte_eth_dev_get_sec_ctx(sa->portid);\n-\t\t\tconst struct rte_security_capability *sec_cap;\n-\n-\t\t\tif (ctx == NULL) {\n-\t\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\"Ethernet device doesn't have security features registered\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n+\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\t\"Failed to create ipsec flow msg: %s\\n\",\n+\t\t\t\terr.message);\n+\t\t\treturn -1;\n+\t\t}\n+\t} else if (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) {\n+\t\tstruct rte_security_ctx *ctx =\n+\t\t\t\t(struct rte_security_ctx *)\n+\t\t\t\trte_eth_dev_get_sec_ctx(sa->portid);\n+\t\tconst struct rte_security_capability *sec_cap;\n \n-\t\t\t/* Set IPsec parameters in conf */\n-\t\t\tset_ipsec_conf(sa, &(sess_conf.ipsec));\n-\n-\t\t\t/* Save SA as userdata for the security session. When\n-\t\t\t * the packet is received, this userdata will be\n-\t\t\t * retrieved using the metadata from the packet.\n-\t\t\t *\n-\t\t\t * The PMD is expected to set similar metadata for other\n-\t\t\t * operations, like rte_eth_event, which are tied to\n-\t\t\t * security session. In such cases, the userdata could\n-\t\t\t * be obtained to uniquely identify the security\n-\t\t\t * parameters denoted.\n-\t\t\t */\n-\n-\t\t\tsess_conf.userdata = (void *) sa;\n-\n-\t\t\tsa->sec_session = rte_security_session_create(ctx,\n-\t\t\t\t\t&sess_conf, ipsec_ctx->session_pool);\n-\t\t\tif (sa->sec_session == NULL) {\n-\t\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\"SEC Session init failed: err: %d\\n\", ret);\n-\t\t\t\treturn -1;\n-\t\t\t}\n+\t\tif (ctx == NULL) {\n+\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\"Ethernet device doesn't have security features registered\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* Set IPsec parameters in conf */\n+\t\tset_ipsec_conf(sa, &(sess_conf.ipsec));\n+\n+\t\t/* Save SA as userdata for the security session. When\n+\t\t * the packet is received, this userdata will be\n+\t\t * retrieved using the metadata from the packet.\n+\t\t *\n+\t\t * The PMD is expected to set similar metadata for other\n+\t\t * operations, like rte_eth_event, which are tied to\n+\t\t * security session. In such cases, the userdata could\n+\t\t * be obtained to uniquely identify the security\n+\t\t * parameters denoted.\n+\t\t */\n+\n+\t\tsess_conf.userdata = (void *) sa;\n+\n+\t\tsa->sec_session = rte_security_session_create(ctx,\n+\t\t\t&sess_conf, pool);\n+\t\tif (sa->sec_session == NULL) {\n+\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\"SEC Session init failed: err: %d\\n\", ret);\n+\t\t\treturn -1;\n+\t\t}\n \n-\t\t\tsec_cap = rte_security_capabilities_get(ctx);\n+\t\tsec_cap = rte_security_capabilities_get(ctx);\n \n-\t\t\tif (sec_cap == NULL) {\n-\t\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\"No capabilities registered\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n+\t\tif (sec_cap == NULL) {\n+\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\"No capabilities registered\\n\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t\t\t/* iterate until ESP tunnel*/\n-\t\t\twhile (sec_cap->action !=\n+\t\t/* iterate until ESP tunnel*/\n+\t\twhile (sec_cap->action !=\n \t\t\t\t\tRTE_SECURITY_ACTION_TYPE_NONE) {\n \n-\t\t\t\tif (sec_cap->action == sa->type &&\n-\t\t\t\t    sec_cap->protocol ==\n-\t\t\t\t\tRTE_SECURITY_PROTOCOL_IPSEC &&\n-\t\t\t\t    sec_cap->ipsec.mode ==\n-\t\t\t\t\tRTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&\n-\t\t\t\t    sec_cap->ipsec.direction == sa->direction)\n-\t\t\t\t\tbreak;\n-\t\t\t\tsec_cap++;\n-\t\t\t}\n+\t\t\tif (sec_cap->action == sa->type &&\n+\t\t\t\tsec_cap->protocol ==\n+\t\t\t\tRTE_SECURITY_PROTOCOL_IPSEC &&\n+\t\t\t\tsec_cap->ipsec.mode ==\n+\t\t\t\tRTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&\n+\t\t\t\tsec_cap->ipsec.direction == sa->direction)\n+\t\t\t\tbreak;\n+\t\t\tsec_cap++;\n+\t\t}\n \n-\t\t\tif (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) {\n-\t\t\t\tRTE_LOG(ERR, IPSEC,\n-\t\t\t\t\"No suitable security capability found\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n+\t\tif (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) {\n+\t\t\tRTE_LOG(ERR, IPSEC,\n+\t\t\t\"No suitable security capability found\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tsa->ol_flags = sec_cap->ol_flags;\n+\t\tsa->security_ctx = ctx;\n+\t} else\n+\t\treturn -EINVAL;\n+\treturn 0;\n+}\n+\n+#define CDEV_IV_SIZE 12\n+\n+static int\n+check_cryptodev_aead_capablity(const struct ipsec_sa *ss, uint8_t dev_id)\n+{\n+\tstruct rte_cryptodev_sym_capability_idx cap_idx;\n+\tconst struct rte_cryptodev_symmetric_capability *cap;\n \n-\t\t\tsa->ol_flags = sec_cap->ol_flags;\n-\t\t\tsa->security_ctx = ctx;\n+\tcap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;\n+\tcap_idx.algo.aead = ss->aead_algo;\n+\n+\tcap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);\n+\tif (cap == NULL)\n+\t\treturn -ENOENT;\n+\n+\treturn rte_cryptodev_sym_capability_check_aead(cap,\n+\t\t\t\t\tss->cipher_key_len,\n+\t\t\t\t\tss->digest_len,\n+\t\t\t\t\tss->aad_len,\n+\t\t\t\t\tCDEV_IV_SIZE);\n+}\n+\n+static int\n+check_cryptodev_capablity(const struct ipsec_sa *ss, uint8_t dev_id)\n+{\n+\tstruct rte_cryptodev_sym_capability_idx cap_idx;\n+\tconst struct rte_cryptodev_symmetric_capability *cap;\n+\tuint16_t auth_iv_len;\n+\tint rc = -1;\n+\n+\tif (ss == NULL)\n+\t\treturn rc;\n+\n+\tif (ss->aead_algo == RTE_CRYPTO_AEAD_AES_GCM)\n+\t\treturn check_cryptodev_aead_capablity(ss, dev_id);\n+\n+\tauth_iv_len = 0;\n+\n+\tcap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;\n+\tcap_idx.algo.auth = ss->auth_algo;\n+\tcap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);\n+\tif (cap != NULL) {\n+\t\trc = rte_cryptodev_sym_capability_check_auth(\n+\t\t\t\tcap, ss->auth_key_len, ss->digest_len,\n+\t\t\t\tauth_iv_len);\n+\t\tif (rc == 0) {\n+\t\t\tcap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;\n+\t\t\tcap_idx.algo.cipher = ss->cipher_algo;\n+\t\t\tcap = rte_cryptodev_sym_capability_get(dev_id,\n+\t\t\t\t\t&cap_idx);\n+\t\t\tif (cap != NULL)\n+\t\t\t\trc = rte_cryptodev_sym_capability_check_cipher(\n+\t\t\t\t\t\tcap, ss->cipher_key_len,\n+\t\t\t\t\t\tss->iv_len);\n \t\t}\n-\t} else {\n-\t\tsa->crypto_session = rte_cryptodev_sym_session_create(\n-\t\t\t\tipsec_ctx->session_pool);\n-\t\trte_cryptodev_sym_session_init(ipsec_ctx->tbl[cdev_id_qp].id,\n-\t\t\t\tsa->crypto_session, sa->xforms,\n-\t\t\t\tipsec_ctx->session_priv_pool);\n-\n-\t\trte_cryptodev_info_get(ipsec_ctx->tbl[cdev_id_qp].id,\n-\t\t\t\t&cdev_info);\n \t}\n-\tsa->cdev_id_qp = cdev_id_qp;\n \n-\treturn 0;\n+\treturn rc;\n+}\n+\n+static int\n+create_crypto_session(struct ipsec_sa *sa, struct rte_mempool *pool)\n+{\n+\tint32_t rc;\n+\tuint32_t devnum, i;\n+\tstruct rte_cryptodev_sym_session *s;\n+\tuint8_t devid[RTE_CRYPTO_MAX_DEVS];\n+\n+\t/* check which cryptodevs support SA */\n+\tdevnum = 0;\n+\tfor (i = 0; i < crypto_dev_num; i++) {\n+\t\trc = check_cryptodev_capablity(sa, crypto_devid[i]);\n+\t\tif (rc == 0)\n+\t\t\tdevid[devnum++] = crypto_devid[i];\n+\t}\n+\n+\tif (devnum == 0)\n+\t\treturn -ENODEV;\n+\n+\ts = rte_cryptodev_sym_session_create(pool);\n+\tif (s == NULL)\n+\t\treturn -ENOMEM;\n+\n+\t/* initialize SA crypto session for all supported devices */\n+\tfor (i = 0; i != devnum; i++) {\n+\t\trc = rte_cryptodev_sym_session_init(devid[i], s, sa->xforms,\n+\t\t\tpool);\n+\t\tif (rc != 0)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (i == devnum) {\n+\t\tsa->crypto_session = s;\n+\t\treturn 0;\n+\t}\n+\n+\t/* failure, do cleanup */\n+\twhile (i-- != 0)\n+\t\trte_cryptodev_sym_session_clear(devid[i], s);\n+\n+\trte_cryptodev_sym_session_free(s);\n+\treturn rc;\n+}\n+\n+int\n+create_session(struct ipsec_sa *sa, struct rte_mempool *pool)\n+{\n+\tif (sa->type != RTE_SECURITY_ACTION_TYPE_NONE)\n+\t\treturn create_sec_session(sa, pool);\n+\telse\n+\t\treturn create_crypto_session(sa, pool);\n }\n \n /*\n@@ -393,13 +461,6 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n \t\t\tpriv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;\n \n \t\t\trte_prefetch0(&priv->sym_cop);\n-\n-\t\t\tif ((unlikely(sa->sec_session == NULL)) &&\n-\t\t\t\t\tcreate_session(ipsec_ctx, sa)) {\n-\t\t\t\trte_pktmbuf_free(pkts[i]);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n \t\t\tsym_cop = get_sym_cop(&priv->cop);\n \t\t\tsym_cop->m_src = pkts[i];\n \n@@ -412,13 +473,6 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n \t\t\tpriv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;\n \n \t\t\trte_prefetch0(&priv->sym_cop);\n-\n-\t\t\tif ((unlikely(sa->crypto_session == NULL)) &&\n-\t\t\t\t\tcreate_session(ipsec_ctx, sa)) {\n-\t\t\t\trte_pktmbuf_free(pkts[i]);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n \t\t\trte_crypto_op_attach_sym_session(&priv->cop,\n \t\t\t\t\tsa->crypto_session);\n \n@@ -429,12 +483,7 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n \t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:\n-\t\t\tif ((unlikely(sa->sec_session == NULL)) &&\n-\t\t\t\t\tcreate_session(ipsec_ctx, sa)) {\n-\t\t\t\trte_pktmbuf_free(pkts[i]);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n+\t\t\tRTE_ASSERT(sa->sec_session != NULL);\n \t\t\tipsec_ctx->ol_pkts[ipsec_ctx->ol_pkts_cnt++] = pkts[i];\n \t\t\tif (sa->ol_flags & RTE_SECURITY_TX_OLOAD_NEED_MDATA)\n \t\t\t\trte_security_set_pkt_metadata(\n@@ -442,17 +491,11 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx,\n \t\t\t\t\t\tsa->sec_session, pkts[i], NULL);\n \t\t\tcontinue;\n \t\tcase RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:\n+\t\t\tRTE_ASSERT(sa->sec_session != NULL);\n \t\t\tpriv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;\n \t\t\tpriv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;\n \n \t\t\trte_prefetch0(&priv->sym_cop);\n-\n-\t\t\tif ((unlikely(sa->sec_session == NULL)) &&\n-\t\t\t\t\tcreate_session(ipsec_ctx, sa)) {\n-\t\t\t\trte_pktmbuf_free(pkts[i]);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n \t\t\trte_security_attach_session(&priv->cop,\n \t\t\t\t\tsa->sec_session);\n \ndiff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h\nindex 99f49d6..804330c 100644\n--- a/examples/ipsec-secgw/ipsec.h\n+++ b/examples/ipsec-secgw/ipsec.h\n@@ -83,6 +83,14 @@ struct app_sa_prm {\n \n extern struct app_sa_prm app_sa_prm;\n \n+/*\n+ * Number of enabled crypto devices\n+ * This number is needed when checking crypto device capabilities\n+ */\n+extern uint8_t crypto_dev_num;\n+/* array of crypto device ID's */\n+extern uint8_t crypto_devid[RTE_CRYPTO_MAX_DEVS];\n+\n struct ipsec_sa {\n \tstruct rte_ipsec_session ips; /* one session per sa for now */\n \tuint32_t spi;\n@@ -306,6 +314,6 @@ void\n enqueue_cop_burst(struct cdev_qp *cqp);\n \n int\n-create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa);\n+create_session(struct ipsec_sa *sa, struct rte_mempool *pool);\n \n #endif /* __IPSEC_H__ */\ndiff --git a/examples/ipsec-secgw/ipsec_process.c b/examples/ipsec-secgw/ipsec_process.c\nindex 3f9cacb..0df6969 100644\n--- a/examples/ipsec-secgw/ipsec_process.c\n+++ b/examples/ipsec-secgw/ipsec_process.c\n@@ -86,39 +86,6 @@ enqueue_cop_bulk(struct cdev_qp *cqp, struct rte_crypto_op *cop[], uint32_t num)\n \tcqp->len = len;\n }\n \n-static inline int\n-fill_ipsec_session(struct rte_ipsec_session *ss, struct ipsec_ctx *ctx,\n-\tstruct ipsec_sa *sa)\n-{\n-\tint32_t rc;\n-\n-\t/* setup crypto section */\n-\tif (ss->type == RTE_SECURITY_ACTION_TYPE_NONE) {\n-\t\tif (sa->crypto_session == NULL) {\n-\t\t\trc = create_session(ctx, sa);\n-\t\t\tif (rc != 0)\n-\t\t\t\treturn rc;\n-\t\t}\n-\t\tss->crypto.ses = sa->crypto_session;\n-\t/* setup session action type */\n-\t} else {\n-\t\tif (sa->sec_session == NULL) {\n-\t\t\trc = create_session(ctx, sa);\n-\t\t\tif (rc != 0)\n-\t\t\t\treturn rc;\n-\t\t}\n-\t\tss->security.ses = sa->sec_session;\n-\t\tss->security.ctx = sa->security_ctx;\n-\t\tss->security.ol_flags = sa->ol_flags;\n-\t}\n-\n-\trc = rte_ipsec_session_prepare(ss);\n-\tif (rc != 0)\n-\t\tmemset(ss, 0, sizeof(*ss));\n-\n-\treturn rc;\n-}\n-\n /*\n  * group input packets byt the SA they belong to.\n  */\n@@ -219,9 +186,8 @@ ipsec_process(struct ipsec_ctx *ctx, struct ipsec_traffic *trf)\n \n \t\tips = &sa->ips;\n \n-\t\t/* no valid HW session for that SA, try to create one */\n-\t\tif (sa == NULL || (ips->crypto.ses == NULL &&\n-\t\t\t\tfill_ipsec_session(ips, ctx, sa) != 0))\n+\t\t/* no valid HW session for that SA */\n+\t\tif (sa == NULL || ips->crypto.ses == NULL)\n \t\t\tk = 0;\n \n \t\t/* process packets inline */\ndiff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c\nindex a7298a3..0f36f5b 100644\n--- a/examples/ipsec-secgw/sa.c\n+++ b/examples/ipsec-secgw/sa.c\n@@ -774,14 +774,14 @@ check_eth_dev_caps(uint16_t portid, uint32_t inbound)\n \treturn 0;\n }\n \n-\n static int\n sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n-\t\tuint32_t nb_entries, uint32_t inbound)\n+\tuint32_t nb_entries, uint32_t inbound, struct socket_ctx *skt_ctx)\n {\n \tstruct ipsec_sa *sa;\n \tuint32_t i, idx;\n \tuint16_t iv_length, aad_length;\n+\tint32_t rc;\n \n \t/* for ESN upper 32 bits of SQN also need to be part of AAD */\n \taad_length = (app_sa_prm.enable_esn != 0) ? sizeof(uint32_t) : 0;\n@@ -902,6 +902,12 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n \n \t\t\tprint_one_sa_rule(sa, inbound);\n \t\t}\n+\t\trc = create_session(sa, skt_ctx->session_pool);\n+\t\tif (rc != 0) {\n+\t\t\tRTE_LOG(ERR, IPSEC_ESP,\n+\t\t\t\t\t\"create_session() failed\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n \t}\n \n \treturn 0;\n@@ -909,16 +915,16 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n \n static inline int\n sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n-\t\tuint32_t nb_entries)\n+\t\tuint32_t nb_entries, struct socket_ctx *skt_ctx)\n {\n-\treturn sa_add_rules(sa_ctx, entries, nb_entries, 0);\n+\treturn sa_add_rules(sa_ctx, entries, nb_entries, 0, skt_ctx);\n }\n \n static inline int\n sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],\n-\t\tuint32_t nb_entries)\n+\t\tuint32_t nb_entries, struct socket_ctx *skt_ctx)\n {\n-\treturn sa_add_rules(sa_ctx, entries, nb_entries, 1);\n+\treturn sa_add_rules(sa_ctx, entries, nb_entries, 1, skt_ctx);\n }\n \n /*\n@@ -1012,10 +1018,12 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,\n \treturn 0;\n }\n \n-static void\n+static int\n fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa,\n \tconst struct ipsec_sa *lsa)\n {\n+\tint32_t rc = 0;\n+\n \tss->sa = sa;\n \tss->type = lsa->type;\n \n@@ -1028,6 +1036,12 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa,\n \t\tss->security.ctx = lsa->security_ctx;\n \t\tss->security.ol_flags = lsa->ol_flags;\n \t}\n+\n+\trc = rte_ipsec_session_prepare(ss);\n+\tif (rc != 0)\n+\t\tmemset(ss, 0, sizeof(*ss));\n+\n+\treturn rc;\n }\n \n /*\n@@ -1062,8 +1076,8 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)\n \tif (rc < 0)\n \t\treturn rc;\n \n-\tfill_ipsec_session(&lsa->ips, sa, lsa);\n-\treturn 0;\n+\trc = fill_ipsec_session(&lsa->ips, sa, lsa);\n+\treturn rc;\n }\n \n /*\n@@ -1141,7 +1155,10 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)\n \t\t\t\t\"context %s in socket %d\\n\", rte_errno,\n \t\t\t\tname, socket_id);\n \n-\t\tsa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in);\n+\t\trc = sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in, ctx);\n+\t\tif (rc != 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\"failed to add inbound rules\\n\");\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@@ -1161,7 +1178,10 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)\n \t\t\t\t\"context %s in socket %d\\n\", rte_errno,\n \t\t\t\tname, socket_id);\n \n-\t\tsa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out);\n+\t\trc = sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx);\n+\t\tif (rc != 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\"failed to add outbound rules\\n\");\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",
    "prefixes": [
        "v4",
        "1/2"
    ]
}