get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 7383,
    "url": "https://patches.dpdk.org/api/patches/7383/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1443826867-21004-7-git-send-email-declan.doherty@intel.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<1443826867-21004-7-git-send-email-declan.doherty@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1443826867-21004-7-git-send-email-declan.doherty@intel.com",
    "date": "2015-10-02T23:01:07",
    "name": "[dpdk-dev,6/6] l2fwd-crypto: crypto",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "4b03bad7a256ddc101648a85deed185be2c1222d",
    "submitter": {
        "id": 11,
        "url": "https://patches.dpdk.org/api/people/11/?format=api",
        "name": "Doherty, Declan",
        "email": "declan.doherty@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1443826867-21004-7-git-send-email-declan.doherty@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/7383/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/7383/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 [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 99E198E8C;\n\tSat,  3 Oct 2015 00:54:36 +0200 (CEST)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n\tby dpdk.org (Postfix) with ESMTP id 047748E97\n\tfor <dev@dpdk.org>; Sat,  3 Oct 2015 00:54:30 +0200 (CEST)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n\tby orsmga103.jf.intel.com with ESMTP; 02 Oct 2015 15:54:28 -0700",
            "from unknown (HELO dwdohert-dpdk-fedora-20.ir.intel.com)\n\t([163.33.213.96])\n\tby orsmga001.jf.intel.com with ESMTP; 02 Oct 2015 15:54:27 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.17,625,1437462000\"; d=\"scan'208\";a=\"783186183\"",
        "From": "Declan Doherty <declan.doherty@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Sat,  3 Oct 2015 00:01:07 +0100",
        "Message-Id": "<1443826867-21004-7-git-send-email-declan.doherty@intel.com>",
        "X-Mailer": "git-send-email 2.4.3",
        "In-Reply-To": "<1443826867-21004-1-git-send-email-declan.doherty@intel.com>",
        "References": "<1443826867-21004-1-git-send-email-declan.doherty@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 6/6] l2fwd-crypto: crypto",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch creates a new sample applicaiton based off the l2fwd\napplication which performs specified crypto operations on IP packet\npayloads which are forwarding.\n\nSigned-off-by: Declan Doherty <declan.doherty@intel.com>\n---\n examples/l2fwd-crypto/Makefile |   50 ++\n examples/l2fwd-crypto/main.c   | 1475 ++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 1525 insertions(+)\n create mode 100644 examples/l2fwd-crypto/Makefile\n create mode 100644 examples/l2fwd-crypto/main.c",
    "diff": "diff --git a/examples/l2fwd-crypto/Makefile b/examples/l2fwd-crypto/Makefile\nnew file mode 100644\nindex 0000000..e8224ca\n--- /dev/null\n+++ b/examples/l2fwd-crypto/Makefile\n@@ -0,0 +1,50 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+#   All rights reserved.\n+#\n+#   Redistribution and use in source and binary forms, with or without\n+#   modification, are permitted provided that the following conditions\n+#   are met:\n+#\n+#     * Redistributions of source code must retain the above copyright\n+#       notice, this list of conditions and the following disclaimer.\n+#     * Redistributions in binary form must reproduce the above copyright\n+#       notice, this list of conditions and the following disclaimer in\n+#       the documentation and/or other materials provided with the\n+#       distribution.\n+#     * Neither the name of Intel Corporation nor the names of its\n+#       contributors may be used to endorse or promote products derived\n+#       from this software without specific prior written permission.\n+#\n+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+ifeq ($(RTE_SDK),)\n+$(error \"Please define RTE_SDK environment variable\")\n+endif\n+\n+# Default target, can be overridden by command line or environment\n+RTE_TARGET ?= x86_64-native-linuxapp-gcc\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+# binary name\n+APP = l2fwd-crypto\n+\n+# all source are stored in SRCS-y\n+SRCS-y := main.c\n+\n+CFLAGS += -O3\n+CFLAGS += $(WERROR_FLAGS)\n+\n+include $(RTE_SDK)/mk/rte.extapp.mk\ndiff --git a/examples/l2fwd-crypto/main.c b/examples/l2fwd-crypto/main.c\nnew file mode 100644\nindex 0000000..c974c9e\n--- /dev/null\n+++ b/examples/l2fwd-crypto/main.c\n@@ -0,0 +1,1475 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <time.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+#include <sys/types.h>\n+#include <sys/queue.h>\n+#include <netinet/in.h>\n+#include <setjmp.h>\n+#include <stdarg.h>\n+#include <ctype.h>\n+#include <errno.h>\n+#include <getopt.h>\n+\n+#include <rte_atomic.h>\n+#include <rte_branch_prediction.h>\n+#include <rte_common.h>\n+#include <rte_cryptodev.h>\n+#include <rte_cycles.h>\n+#include <rte_debug.h>\n+#include <rte_eal.h>\n+#include <rte_ether.h>\n+#include <rte_ethdev.h>\n+#include <rte_interrupts.h>\n+#include <rte_ip.h>\n+#include <rte_launch.h>\n+#include <rte_lcore.h>\n+#include <rte_log.h>\n+#include <rte_malloc.h>\n+#include <rte_mbuf.h>\n+#include <rte_memcpy.h>\n+#include <rte_memory.h>\n+#include <rte_mempool.h>\n+#include <rte_memzone.h>\n+#include <rte_pci.h>\n+#include <rte_per_lcore.h>\n+#include <rte_prefetch.h>\n+#include <rte_random.h>\n+#include <rte_ring.h>\n+\n+#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1\n+\n+#define NB_MBUF   8192\n+\n+#define MAX_PKT_BURST 32\n+#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */\n+\n+/*\n+ * Configurable number of RX/TX ring descriptors\n+ */\n+#define RTE_TEST_RX_DESC_DEFAULT 128\n+#define RTE_TEST_TX_DESC_DEFAULT 512\n+static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;\n+static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;\n+\n+/* ethernet addresses of ports */\n+static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];\n+\n+/* mask of enabled ports */\n+static uint64_t l2fwd_enabled_port_mask;\n+static uint64_t l2fwd_enabled_crypto_mask;\n+\n+/* list of enabled ports */\n+static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];\n+\n+\n+struct pkt_buffer {\n+\tunsigned len;\n+\tstruct rte_mbuf *buffer[MAX_PKT_BURST];\n+};\n+\n+#define MAX_RX_QUEUE_PER_LCORE 16\n+#define MAX_TX_QUEUE_PER_PORT 16\n+\n+enum l2fwd_crypto_xform_chain {\n+\tL2FWD_CRYPTO_CIPHER_HASH,\n+\tL2FWD_CRYPTO_HASH_CIPHER\n+};\n+\n+/** l2fwd crypto application command line options */\n+struct l2fwd_crypto_options {\n+\tunsigned portmask;\n+\tunsigned nb_ports_per_lcore;\n+\tunsigned refresh_period;\n+\tunsigned single_lcore:1;\n+\tunsigned no_stats_printing:1;\n+\n+\tenum rte_cryptodev_type cdev_type;\n+\tunsigned sessionless:1;\n+\n+\tenum l2fwd_crypto_xform_chain xform_chain;\n+\n+\tstruct rte_crypto_xform cipher_xform;\n+\tuint8_t ckey_data[32];\n+\n+\tstruct rte_crypto_key iv_key;\n+\tuint8_t ivkey_data[16];\n+\n+\tstruct rte_crypto_xform auth_xform;\n+\tuint8_t akey_data[128];\n+};\n+\n+/** l2fwd crypto lcore params */\n+struct l2fwd_crypto_params {\n+\tuint8_t dev_id;\n+\tuint8_t qp_id;\n+\n+\tunsigned digest_length;\n+\tunsigned block_size;\n+\n+\tstruct rte_crypto_key iv_key;\n+\tstruct rte_cryptodev_session *session;\n+};\n+\n+/** lcore configuration */\n+struct lcore_queue_conf {\n+\tunsigned nb_rx_ports;\n+\tunsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];\n+\n+\tunsigned nb_crypto_devs;\n+\tunsigned cryptodev_list[MAX_RX_QUEUE_PER_LCORE];\n+\n+\tstruct pkt_buffer crypto_pkt_buf[RTE_MAX_ETHPORTS];\n+\tstruct pkt_buffer tx_pkt_buf[RTE_MAX_ETHPORTS];\n+} __rte_cache_aligned;\n+\n+struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];\n+\n+static const struct rte_eth_conf port_conf = {\n+\t.rxmode = {\n+\t\t.split_hdr_size = 0,\n+\t\t.header_split   = 0, /**< Header Split disabled */\n+\t\t.hw_ip_checksum = 0, /**< IP checksum offload disabled */\n+\t\t.hw_vlan_filter = 0, /**< VLAN filtering disabled */\n+\t\t.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */\n+\t\t.hw_strip_crc   = 0, /**< CRC stripped by hardware */\n+\t},\n+\t.txmode = {\n+\t\t.mq_mode = ETH_MQ_TX_NONE,\n+\t},\n+};\n+\n+struct rte_mempool *l2fwd_pktmbuf_pool;\n+struct rte_mempool *l2fwd_crtpto_op_pool;\n+\n+/* Per-port statistics struct */\n+struct l2fwd_port_statistics {\n+\tuint64_t tx;\n+\tuint64_t rx;\n+\n+\tuint64_t crypto_enqueued;\n+\tuint64_t crypto_dequeued;\n+\n+\tuint64_t dropped;\n+} __rte_cache_aligned;\n+\n+struct l2fwd_crypto_statistics {\n+\tuint64_t enqueued;\n+\tuint64_t dequeued;\n+\n+\tuint64_t errors;\n+} __rte_cache_aligned;\n+\n+struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];\n+struct l2fwd_crypto_statistics crypto_statistics[RTE_MAX_ETHPORTS];\n+\n+/* A tsc-based timer responsible for triggering statistics printout */\n+#define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */\n+#define MAX_TIMER_PERIOD 86400 /* 1 day max */\n+static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */\n+\n+uint64_t total_packets_dropped = 0, total_packets_tx = 0, total_packets_rx = 0,\n+\ttotal_packets_enqueued = 0, total_packets_dequeued = 0,\n+\ttotal_packets_errors = 0;\n+\n+/* Print out statistics on packets dropped */\n+static void\n+print_stats(void)\n+{\n+\tunsigned portid;\n+\tuint64_t cdevid;\n+\n+\n+\tconst char clr[] = { 27, '[', '2', 'J', '\\0' };\n+\tconst char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\\0' };\n+\n+\t\t/* Clear screen and move to top left */\n+\tprintf(\"%s%s\", clr, topLeft);\n+\n+\tprintf(\"\\nPort statistics ====================================\");\n+\n+\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n+\t\t/* skip disabled ports */\n+\t\tif ((l2fwd_enabled_port_mask & (1 << portid)) == 0)\n+\t\t\tcontinue;\n+\t\tprintf(\"\\nStatistics for port %u ------------------------------\"\n+\t\t\t   \"\\nPackets sent: %32\"PRIu64\n+\t\t\t   \"\\nPackets received: %28\"PRIu64\n+\t\t\t   \"\\nPackets dropped: %29\"PRIu64,\n+\t\t\t   portid,\n+\t\t\t   port_statistics[portid].tx,\n+\t\t\t   port_statistics[portid].rx,\n+\t\t\t   port_statistics[portid].dropped);\n+\n+\t\ttotal_packets_dropped += port_statistics[portid].dropped;\n+\t\ttotal_packets_tx += port_statistics[portid].tx;\n+\t\ttotal_packets_rx += port_statistics[portid].rx;\n+\t}\n+\tprintf(\"\\nCrypto statistics ==================================\");\n+\n+\tfor (cdevid = 0; cdevid < RTE_CRYPTO_MAX_DEVS; cdevid++) {\n+\t\t/* skip disabled ports */\n+\t\tif ((l2fwd_enabled_crypto_mask & (1lu << cdevid)) == 0)\n+\t\t\tcontinue;\n+\t\tprintf(\"\\nStatistics for cryptodev %lu -------------------------\"\n+\t\t\t   \"\\nPackets enqueued: %28\"PRIu64\n+\t\t\t   \"\\nPackets dequeued: %28\"PRIu64\n+\t\t\t   \"\\nPackets errors: %30\"PRIu64,\n+\t\t\t   cdevid,\n+\t\t\t   crypto_statistics[cdevid].enqueued,\n+\t\t\t   crypto_statistics[cdevid].dequeued,\n+\t\t\t   crypto_statistics[cdevid].errors);\n+\n+\t\ttotal_packets_enqueued += crypto_statistics[cdevid].enqueued;\n+\t\ttotal_packets_dequeued += crypto_statistics[cdevid].dequeued;\n+\t\ttotal_packets_errors += crypto_statistics[cdevid].errors;\n+\t}\n+\tprintf(\"\\nAggregate statistics ===============================\"\n+\t\t   \"\\nTotal packets received: %22\"PRIu64\n+\t\t   \"\\nTotal packets enqueued: %22\"PRIu64\n+\t\t   \"\\nTotal packets dequeued: %22\"PRIu64\n+\t\t   \"\\nTotal packets sent: %26\"PRIu64\n+\t\t   \"\\nTotal packets dropped: %23\"PRIu64\n+\t\t   \"\\nTotal packets crypto errors: %17\"PRIu64,\n+\t\t   total_packets_rx,\n+\t\t   total_packets_enqueued,\n+\t\t   total_packets_dequeued,\n+\t\t   total_packets_tx,\n+\t\t   total_packets_dropped,\n+\t\t   total_packets_errors);\n+\tprintf(\"\\n====================================================\\n\");\n+}\n+\n+\n+\n+static int\n+l2fwd_crypto_send_burst(struct lcore_queue_conf *qconf, unsigned n,\n+\t\tstruct l2fwd_crypto_params *cparams)\n+{\n+\tstruct rte_mbuf **pkt_buffer;\n+\tunsigned ret;\n+\n+\tpkt_buffer = (struct rte_mbuf **)\n+\t\t\tqconf->crypto_pkt_buf[cparams->dev_id].buffer;\n+\n+\tret = rte_cryptodev_enqueue_burst(cparams->dev_id, cparams->qp_id,\n+\t\t\tpkt_buffer, (uint16_t) n);\n+\tcrypto_statistics[cparams->dev_id].enqueued += ret;\n+\tif (unlikely(ret < n)) {\n+\t\tcrypto_statistics[cparams->dev_id].errors += (n - ret);\n+\t\tdo {\n+\t\t\trte_pktmbuf_free(pkt_buffer[ret]);\n+\t\t} while (++ret < n);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+l2fwd_crypto_enqueue(struct rte_mbuf *m, struct l2fwd_crypto_params *cparams)\n+{\n+\tunsigned lcore_id, len;\n+\tstruct lcore_queue_conf *qconf;\n+\n+\tlcore_id = rte_lcore_id();\n+\n+\tqconf = &lcore_queue_conf[lcore_id];\n+\tlen = qconf->crypto_pkt_buf[cparams->dev_id].len;\n+\tqconf->crypto_pkt_buf[cparams->dev_id].buffer[len] = m;\n+\tlen++;\n+\n+\t/* enough pkts to be sent */\n+\tif (len == MAX_PKT_BURST) {\n+\t\tl2fwd_crypto_send_burst(qconf, MAX_PKT_BURST, cparams);\n+\t\tlen = 0;\n+\t}\n+\n+\tqconf->crypto_pkt_buf[cparams->dev_id].len = len;\n+\treturn 0;\n+}\n+\n+static int\n+l2fwd_simple_crypto_enqueue(struct rte_mbuf *m,\n+\t\tstruct rte_crypto_op_data *c_op,\n+\t\tstruct l2fwd_crypto_params *cparams)\n+{\n+\tstruct ether_hdr *eth_hdr;\n+\tstruct ipv4_hdr *ip_hdr;\n+\n+\tunsigned ipdata_offset, pad_len, data_len;\n+\tchar *padding;\n+\n+\teth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);\n+\n+\tif (eth_hdr->ether_type != rte_cpu_to_be_16(ETHER_TYPE_IPv4))\n+\t\treturn -1;\n+\n+\tipdata_offset = sizeof(struct ether_hdr);\n+\n+\tip_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(m, char *) +\n+\t\t\tipdata_offset);\n+\n+\tipdata_offset += (ip_hdr->version_ihl & IPV4_HDR_IHL_MASK)\n+\t\t\t* IPV4_IHL_MULTIPLIER;\n+\n+\n+\t/* Zero pad data to be crypto'd so it is block aligned */\n+\tdata_len  = rte_pktmbuf_data_len(m) - ipdata_offset;\n+\tpad_len = data_len % cparams->block_size ? cparams->block_size -\n+\t\t\t(data_len % cparams->block_size) : 0;\n+\n+\tif (pad_len) {\n+\t\tpadding = rte_pktmbuf_append(m, pad_len);\n+\t\tif (unlikely(!padding))\n+\t\t\treturn -1;\n+\n+\t\tdata_len += pad_len;\n+\t\tmemset(padding, 0, pad_len);\n+\t}\n+\n+\t/* Set crypto operation data parameters */\n+\trte_crypto_op_attach_session(c_op, cparams->session);\n+\n+\t/* Append space for digest to end of packet */\n+\tc_op->digest.data = (uint8_t *)rte_pktmbuf_append(m,\n+\t\t\tcparams->digest_length);\n+\tc_op->digest.phys_addr = rte_pktmbuf_mtophys_offset(m,\n+\t\t\trte_pktmbuf_pkt_len(m) - cparams->digest_length);\n+\tc_op->digest.length = cparams->digest_length;\n+\n+\tc_op->iv.data = cparams->iv_key.data;\n+\tc_op->iv.phys_addr = cparams->iv_key.phys_addr;\n+\tc_op->iv.length = cparams->iv_key.length;\n+\n+\tc_op->data.to_cipher.offset = ipdata_offset;\n+\tc_op->data.to_cipher.length = data_len;\n+\n+\tc_op->data.to_hash.offset = ipdata_offset;\n+\tc_op->data.to_hash.length = data_len;\n+\n+\trte_pktmbuf_attach_crypto_op(m, c_op);\n+\n+\treturn l2fwd_crypto_enqueue(m, cparams);\n+}\n+\n+\n+/* Send the burst of packets on an output interface */\n+static int\n+l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)\n+{\n+\tstruct rte_mbuf **pkt_buffer;\n+\tunsigned ret;\n+\tunsigned queueid = 0;\n+\n+\tpkt_buffer = (struct rte_mbuf **)qconf->tx_pkt_buf[port].buffer;\n+\n+\tret = rte_eth_tx_burst(port, (uint16_t) queueid, pkt_buffer,\n+\t\t\t(uint16_t)n);\n+\tport_statistics[port].tx += ret;\n+\tif (unlikely(ret < n)) {\n+\t\tport_statistics[port].dropped += (n - ret);\n+\t\tdo {\n+\t\t\trte_pktmbuf_free(pkt_buffer[ret]);\n+\t\t} while (++ret < n);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* Enqueue packets for TX and prepare them to be sent */\n+static int\n+l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)\n+{\n+\tunsigned lcore_id, len;\n+\tstruct lcore_queue_conf *qconf;\n+\n+\tlcore_id = rte_lcore_id();\n+\n+\tqconf = &lcore_queue_conf[lcore_id];\n+\tlen = qconf->tx_pkt_buf[port].len;\n+\tqconf->tx_pkt_buf[port].buffer[len] = m;\n+\tlen++;\n+\n+\t/* enough pkts to be sent */\n+\tif (unlikely(len == MAX_PKT_BURST)) {\n+\t\tl2fwd_send_burst(qconf, MAX_PKT_BURST, port);\n+\t\tlen = 0;\n+\t}\n+\n+\tqconf->tx_pkt_buf[port].len = len;\n+\treturn 0;\n+}\n+\n+static void\n+l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)\n+{\n+\tstruct ether_hdr *eth;\n+\tvoid *tmp;\n+\tunsigned dst_port;\n+\n+\tdst_port = l2fwd_dst_ports[portid];\n+\teth = rte_pktmbuf_mtod(m, struct ether_hdr *);\n+\n+\t/* 02:00:00:00:00:xx */\n+\ttmp = &eth->d_addr.addr_bytes[0];\n+\t*((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40);\n+\n+\t/* src addr */\n+\tether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);\n+\n+\tl2fwd_send_packet(m, (uint8_t) dst_port);\n+}\n+\n+/** Generate random key */\n+static void\n+generate_random_key(uint8_t *key, unsigned length)\n+{\n+\tunsigned i;\n+\n+\tfor (i = 0; i < length; i++)\n+\t\tkey[i] = rand() % 0xff;\n+}\n+\n+static struct rte_cryptodev_session *\n+initialize_crypto_session(struct l2fwd_crypto_options *options,\n+\t\tuint8_t cdev_id)\n+{\n+\tstruct rte_crypto_xform *first_xform;\n+\n+\tif (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH) {\n+\t\tfirst_xform = &options->cipher_xform;\n+\t\tfirst_xform->next = &options->auth_xform;\n+\t} else {\n+\t\tfirst_xform = &options->auth_xform;\n+\t\tfirst_xform->next = &options->cipher_xform;\n+\t}\n+\n+\t/* Setup Cipher Parameters */\n+\treturn rte_cryptodev_session_create(cdev_id, first_xform);\n+}\n+\n+static void\n+l2fwd_crypto_options_print(struct l2fwd_crypto_options *options);\n+\n+/* main processing loop */\n+static void\n+l2fwd_main_loop(struct l2fwd_crypto_options *options)\n+{\n+\tstruct rte_mbuf *m, *pkts_burst[MAX_PKT_BURST];\n+\tunsigned lcore_id = rte_lcore_id();\n+\tuint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;\n+\tunsigned i, j, portid, nb_rx;\n+\tstruct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id];\n+\tconst uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /\n+\t\t\tUS_PER_S * BURST_TX_DRAIN_US;\n+\tstruct l2fwd_crypto_params *cparams;\n+\tstruct l2fwd_crypto_params port_cparams[qconf->nb_crypto_devs];\n+\n+\tif (qconf->nb_rx_ports == 0) {\n+\t\tRTE_LOG(INFO, L2FWD, \"lcore %u has nothing to do\\n\", lcore_id);\n+\t\treturn;\n+\t}\n+\n+\tRTE_LOG(INFO, L2FWD, \"entering main loop on lcore %u\\n\", lcore_id);\n+\n+\tl2fwd_crypto_options_print(options);\n+\n+\tfor (i = 0; i < qconf->nb_rx_ports; i++) {\n+\n+\t\tportid = qconf->rx_port_list[i];\n+\t\tRTE_LOG(INFO, L2FWD, \" -- lcoreid=%u portid=%u\\n\", lcore_id,\n+\t\t\tportid);\n+\t}\n+\n+\tfor (i = 0; i < qconf->nb_crypto_devs; i++) {\n+\t\tport_cparams[i].dev_id = qconf->cryptodev_list[i];\n+\t\tport_cparams[i].qp_id = 0;\n+\n+\t\tport_cparams[i].block_size = 64;\n+\t\tport_cparams[i].digest_length = 20;\n+\n+\t\tport_cparams[i].iv_key.data =\n+\t\t\t\t(uint8_t *)rte_malloc(NULL, 16, 8);\n+\t\tport_cparams[i].iv_key.length = 16;\n+\t\tport_cparams[i].iv_key.phys_addr = rte_malloc_virt2phy(\n+\t\t\t\t(void *)port_cparams[i].iv_key.data);\n+\t\tgenerate_random_key(port_cparams[i].iv_key.data,\n+\t\t\t\tsizeof(cparams[i].iv_key.length));\n+\n+\t\tport_cparams[i].session = initialize_crypto_session(options,\n+\t\t\t\tport_cparams[i].dev_id);\n+\n+\t\tif (port_cparams[i].session == NULL)\n+\t\t\treturn;\n+\t\tRTE_LOG(INFO, L2FWD, \" -- lcoreid=%u cryptoid=%u\\n\", lcore_id,\n+\t\t\t\tport_cparams[i].dev_id);\n+\t}\n+\n+\twhile (1) {\n+\n+\t\tcur_tsc = rte_rdtsc();\n+\n+\t\t/*\n+\t\t * TX burst queue drain\n+\t\t */\n+\t\tdiff_tsc = cur_tsc - prev_tsc;\n+\t\tif (unlikely(diff_tsc > drain_tsc)) {\n+\n+\t\t\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {\n+\t\t\t\tif (qconf->tx_pkt_buf[portid].len == 0)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tl2fwd_send_burst(&lcore_queue_conf[lcore_id],\n+\t\t\t\t\t\t qconf->tx_pkt_buf[portid].len,\n+\t\t\t\t\t\t (uint8_t) portid);\n+\t\t\t\tqconf->tx_pkt_buf[portid].len = 0;\n+\t\t\t}\n+\n+\t\t\t/* if timer is enabled */\n+\t\t\tif (timer_period > 0) {\n+\n+\t\t\t\t/* advance the timer */\n+\t\t\t\ttimer_tsc += diff_tsc;\n+\n+\t\t\t\t/* if timer has reached its timeout */\n+\t\t\t\tif (unlikely(timer_tsc >=\n+\t\t\t\t\t\t(uint64_t)timer_period)) {\n+\n+\t\t\t\t\t/* do this only on master core */\n+\t\t\t\t\tif (lcore_id == rte_get_master_lcore() &&\n+\t\t\t\t\t\t\t!options->no_stats_printing) {\n+\t\t\t\t\t\tprint_stats();\n+\t\t\t\t\t\t/* reset the timer */\n+\t\t\t\t\t\ttimer_tsc = 0;\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\tprev_tsc = cur_tsc;\n+\t\t}\n+\n+\t\t/*\n+\t\t * Read packet from RX queues\n+\t\t */\n+\t\tfor (i = 0; i < qconf->nb_rx_ports; i++) {\n+\t\t\tstruct rte_crypto_op_data *c_op;\n+\n+\t\t\tportid = qconf->rx_port_list[i];\n+\n+\t\t\tif (options->single_lcore)\n+\t\t\t\tcparams = &port_cparams[0];\n+\t\t\telse\n+\t\t\t\tcparams = &port_cparams[i];\n+\n+\t\t\tnb_rx = rte_eth_rx_burst((uint8_t) portid, 0,\n+\t\t\t\t\t\t pkts_burst, MAX_PKT_BURST);\n+\n+\t\t\tport_statistics[portid].rx += nb_rx;\n+\n+\t\t\t/* Enqueue packets from Crypto device*/\n+\t\t\tfor (j = 0; j < nb_rx; j++) {\n+\t\t\t\tm = pkts_burst[j];\n+\t\t\t\tc_op = rte_crypto_op_alloc(\n+\t\t\t\t\t\tl2fwd_crtpto_op_pool);\n+\t\t\t\trte_prefetch0(rte_pktmbuf_mtod(m, void *));\n+\t\t\t\trte_prefetch0((void *)c_op);\n+\t\t\t\tl2fwd_simple_crypto_enqueue(m, c_op, cparams);\n+\t\t\t}\n+\n+\t\t\t/* Dequeue packets from Crypto device */\n+\t\t\tnb_rx = rte_cryptodev_dequeue_burst(\n+\t\t\t\t\tcparams->dev_id, cparams->qp_id,\n+\t\t\t\t\tpkts_burst, MAX_PKT_BURST);\n+\t\t\tcrypto_statistics[cparams->dev_id].dequeued += nb_rx;\n+\n+\t\t\t/* Forward crypto'd packets */\n+\t\t\tfor (j = 0; j < nb_rx; j++) {\n+\t\t\t\tm = pkts_burst[j];\n+\t\t\t\trte_crypto_op_free(m->crypto_op);\n+\t\t\t\trte_prefetch0(rte_pktmbuf_mtod(m, void *));\n+\t\t\t\tl2fwd_simple_forward(m, portid);\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+static int\n+l2fwd_launch_one_lcore(void *arg)\n+{\n+\tl2fwd_main_loop((struct l2fwd_crypto_options *)arg);\n+\treturn 0;\n+}\n+\n+/* Display command line arguments usage */\n+static void\n+l2fwd_crypto_usage(const char *prgname)\n+{\n+\tprintf(\"%s [EAL options] -- --cdev TYPE [optional parameters]\\n\"\n+\t\t\"  -p PORTMASK: hexadecimal bitmask of ports to configure\\n\"\n+\t\t\"  -q NQ: number of queue (=ports) per lcore (default is 1)\\n\"\n+\t\t\"  -s manage all ports from single lcore\"\n+\t\t\"  -t PERIOD: statistics will be refreshed each PERIOD seconds\"\n+\t\t\" (0 to disable, 10 default, 86400 maximum)\\n\"\n+\n+\t\t\"  --cdev AESNI_MB / QAT\\n\"\n+\t\t\"  --chain HASH_CIPHER / CIPHER_HASH\\n\"\n+\n+\t\t\"  --cipher_algo ALGO\\n\"\n+\t\t\"  --cipher_op ENCRYPT / DECRYPT\\n\"\n+\t\t\"  --cipher_key KEY\\n\"\n+\n+\t\t\"  --auth ALGO\\n\"\n+\t\t\"  --auth_op GENERATE / VERIFY\\n\"\n+\t\t\"  --auth_key KEY\\n\"\n+\n+\t\t\"  --sessionless\\n\",\n+\t       prgname);\n+}\n+\n+/** Parse crypto device type command line argument */\n+static int\n+parse_cryptodev_type(enum rte_cryptodev_type *type, char *optarg)\n+{\n+\tif (strcmp(\"AESNI_MB\", optarg) == 0) {\n+\t\t*type = RTE_CRYPTODEV_AESNI_MB_PMD;\n+\t\treturn 0;\n+\t} else if (strcmp(\"QAT\", optarg) == 0) {\n+\t\t*type = RTE_CRYPTODEV_QAT_PMD;\n+\t\treturn 0;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+/** Parse crypto chain xform command line argument */\n+static int\n+parse_crypto_opt_chain(struct l2fwd_crypto_options *options, char *optarg)\n+{\n+\tif (strcmp(\"CIPHER_HASH\", optarg) == 0) {\n+\t\toptions->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;\n+\t\treturn 0;\n+\t} else if (strcmp(\"HASH_CIPHER\", optarg) == 0) {\n+\t\toptions->xform_chain = L2FWD_CRYPTO_HASH_CIPHER;\n+\t\treturn 0;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+/** Parse crypto cipher algo option command line argument */\n+static int\n+parse_cipher_algo(enum rte_crypto_cipher_algorithm *algo, char *optarg)\n+{\n+\tif (strcmp(\"AES_CBC\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;\n+\t\treturn 0;\n+\t} else if (strcmp(\"AES_GCM\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_CIPHER_AES_GCM;\n+\t\treturn 0;\n+\t}\n+\n+\tprintf(\"Cipher algorithm  not supported!\\n\");\n+\treturn -1;\n+}\n+\n+/** Parse crypto cipher operation command line argument */\n+static int\n+parse_cipher_op(enum rte_crypto_cipher_operation *op, char *optarg)\n+{\n+\tif (strcmp(\"ENCRYPT\", optarg) == 0) {\n+\t\t*op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;\n+\t\treturn 0;\n+\t} else if (strcmp(\"DECRYPT\", optarg) == 0) {\n+\t\t*op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;\n+\t\treturn 0;\n+\t}\n+\n+\tprintf(\"Cipher operation not supported!\\n\");\n+\treturn -1;\n+}\n+\n+/** Parse crypto key command line argument */\n+static int\n+parse_key(struct rte_crypto_key *key __rte_unused,\n+\t\tunsigned length __rte_unused, char *arg __rte_unused)\n+{\n+\tprintf(\"Currently an unsupported argument!\\n\");\n+\treturn -1;\n+}\n+\n+/** Parse crypto cipher operation command line argument */\n+static int\n+parse_auth_algo(enum rte_crypto_auth_algorithm *algo, char *optarg)\n+{\n+\tif (strcmp(\"SHA1\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_HASH_SHA1;\n+\t\treturn 0;\n+\t} else if (strcmp(\"SHA1_HMAC\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;\n+\t\treturn 0;\n+\t} else if (strcmp(\"SHA224\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_HASH_SHA224;\n+\t\treturn 0;\n+\t} else if (strcmp(\"SHA224_HMAC\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_HASH_SHA224_HMAC;\n+\t\treturn 0;\n+\t} else if (strcmp(\"SHA256\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_HASH_SHA256;\n+\t\treturn 0;\n+\t} else if (strcmp(\"SHA256_HMAC\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;\n+\t\treturn 0;\n+\t} else if (strcmp(\"SHA512\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_HASH_SHA256;\n+\t\treturn 0;\n+\t} else if (strcmp(\"SHA512_HMAC\", optarg) == 0) {\n+\t\t*algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;\n+\t\treturn 0;\n+\t}\n+\n+\tprintf(\"Authentication algorithm specified not supported!\\n\");\n+\treturn -1;\n+}\n+\n+static int\n+parse_auth_op(enum rte_crypto_auth_operation *op, char *optarg)\n+{\n+\tif (strcmp(\"VERIFY\", optarg) == 0) {\n+\t\t*op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;\n+\t\treturn 0;\n+\t} else if (strcmp(\"GENERATE\", optarg) == 0) {\n+\t\t*op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;\n+\t\treturn 0;\n+\t}\n+\n+\tprintf(\"Authentication operation specified not supported!\\n\");\n+\treturn -1;\n+}\n+\n+/** Parse long options */\n+static int\n+l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,\n+\t\tstruct option *lgopts, int option_index)\n+{\n+\tif (strcmp(lgopts[option_index].name, \"no_stats\") == 0) {\n+\t\toptions->no_stats_printing = 1;\n+\t\treturn 0;\n+\t}\n+\n+\tif (strcmp(lgopts[option_index].name, \"cdev_type\") == 0)\n+\t\treturn parse_cryptodev_type(&options->cdev_type, optarg);\n+\n+\telse if (strcmp(lgopts[option_index].name, \"chain\") == 0)\n+\t\treturn parse_crypto_opt_chain(options, optarg);\n+\n+\t/* Cipher options */\n+\telse if (strcmp(lgopts[option_index].name, \"cipher_algo\") == 0)\n+\t\treturn parse_cipher_algo(&options->cipher_xform.cipher.algo,\n+\t\t\t\toptarg);\n+\n+\telse if (strcmp(lgopts[option_index].name, \"cipher_op\") == 0)\n+\t\treturn parse_cipher_op(&options->cipher_xform.cipher.op,\n+\t\t\t\toptarg);\n+\n+\telse if (strcmp(lgopts[option_index].name, \"cipher_key\") == 0)\n+\t\treturn parse_key(&options->cipher_xform.cipher.key,\n+\t\t\t\tsizeof(options->ckey_data), optarg);\n+\n+\telse if (strcmp(lgopts[option_index].name, \"iv\") == 0)\n+\t\treturn parse_key(&options->iv_key, sizeof(options->ivkey_data),\n+\t\t\t\toptarg);\n+\n+\t/* Authentication options */\n+\telse if (strcmp(lgopts[option_index].name, \"auth_algo\") == 0)\n+\t\treturn parse_auth_algo(&options->cipher_xform.auth.algo,\n+\t\t\t\toptarg);\n+\n+\telse if (strcmp(lgopts[option_index].name, \"auth_op\") == 0)\n+\t\treturn parse_auth_op(&options->cipher_xform.auth.op,\n+\t\t\t\toptarg);\n+\n+\telse if (strcmp(lgopts[option_index].name, \"auth_key\") == 0)\n+\t\treturn parse_key(&options->auth_xform.auth.key,\n+\t\t\t\tsizeof(options->akey_data), optarg);\n+\n+\telse if (strcmp(lgopts[option_index].name, \"sessionless\") == 0) {\n+\t\toptions->sessionless = 1;\n+\t\treturn 0;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+/** Parse port mask */\n+static int\n+l2fwd_crypto_parse_portmask(struct l2fwd_crypto_options *options,\n+\t\tconst char *q_arg)\n+{\n+\tchar *end = NULL;\n+\tunsigned long pm;\n+\n+\t/* parse hexadecimal string */\n+\tpm = strtoul(q_arg, &end, 16);\n+\tif ((pm == '\\0') || (end == NULL) || (*end != '\\0'))\n+\t\tpm = 0;\n+\n+\toptions->portmask = pm;\n+\tif (options->portmask == 0) {\n+\t\tprintf(\"invalid portmask specified\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn pm;\n+}\n+\n+/** Parse number of queues */\n+static int\n+l2fwd_crypto_parse_nqueue(struct l2fwd_crypto_options *options,\n+\t\tconst char *q_arg)\n+{\n+\tchar *end = NULL;\n+\tunsigned long n;\n+\n+\t/* parse hexadecimal string */\n+\tn = strtoul(q_arg, &end, 10);\n+\tif ((q_arg[0] == '\\0') || (end == NULL) || (*end != '\\0'))\n+\t\tn = 0;\n+\telse if (n >= MAX_RX_QUEUE_PER_LCORE)\n+\t\tn = 0;\n+\n+\toptions->nb_ports_per_lcore = n;\n+\tif (options->nb_ports_per_lcore == 0) {\n+\t\tprintf(\"invalid number of ports selected\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/** Parse timer period */\n+static int\n+l2fwd_crypto_parse_timer_period(struct l2fwd_crypto_options *options,\n+\t\tconst char *q_arg)\n+{\n+\tchar *end = NULL;\n+\tint n;\n+\n+\t/* parse number string */\n+\tn = strtol(q_arg, &end, 10);\n+\tif ((q_arg[0] == '\\0') || (end == NULL) || (*end != '\\0'))\n+\t\tn = 0;\n+\n+\tif (n >= MAX_TIMER_PERIOD)\n+\t\tn = 0;\n+\n+\toptions->refresh_period = n * 1000 * TIMER_MILLISECOND;\n+\tif (options->refresh_period == 0) {\n+\t\tprintf(\"invalid refresh period specified\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/** Generate default options for application */\n+static void\n+l2fwd_crypto_default_options(struct l2fwd_crypto_options *options)\n+{\n+\tsrand(time(NULL));\n+\n+\toptions->portmask = 0xffffffff;\n+\toptions->nb_ports_per_lcore = 1;\n+\toptions->refresh_period = 10000;\n+\toptions->single_lcore = 0;\n+\toptions->no_stats_printing = 0;\n+\n+\toptions->cdev_type = RTE_CRYPTODEV_AESNI_MB_PMD;\n+\toptions->sessionless = 0;\n+\toptions->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;\n+\n+\t/* Cipher Data */\n+\toptions->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;\n+\toptions->cipher_xform.next = NULL;\n+\n+\toptions->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;\n+\toptions->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;\n+\n+\tgenerate_random_key(options->ckey_data, sizeof(options->ckey_data));\n+\n+\toptions->cipher_xform.cipher.key.data = options->ckey_data;\n+\toptions->cipher_xform.cipher.key.phys_addr = 0;\n+\toptions->cipher_xform.cipher.key.length = 16;\n+\n+\n+\t/* Authentication Data */\n+\toptions->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;\n+\toptions->auth_xform.next = NULL;\n+\n+\toptions->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;\n+\toptions->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;\n+\n+\toptions->auth_xform.auth.add_auth_data_length = 0;\n+\toptions->auth_xform.auth.digest_length = 20;\n+\n+\tgenerate_random_key(options->akey_data, sizeof(options->akey_data));\n+\n+\toptions->auth_xform.auth.key.data = options->akey_data;\n+\toptions->auth_xform.auth.key.phys_addr = 0;\n+\toptions->auth_xform.auth.key.length = 20;\n+}\n+\n+static void\n+l2fwd_crypto_options_print(struct l2fwd_crypto_options *options)\n+{\n+\tprintf(\"Options:-\\nn\");\n+\tprintf(\"portmask: %x\\n\", options->portmask);\n+\tprintf(\"ports per lcore: %u\\n\", options->nb_ports_per_lcore);\n+\tprintf(\"refresh period : %u\\n\", options->refresh_period);\n+\tprintf(\"single lcore mode: %s\\n\",\n+\t\t\toptions->single_lcore ? \"enabled\" : \"disabled\");\n+\tprintf(\"stats_printing: %s\\n\",\n+\t\t\toptions->no_stats_printing ? \"disabled\" : \"enabled\");\n+\n+\tswitch (options->cdev_type) {\n+\tcase RTE_CRYPTODEV_AESNI_MB_PMD:\n+\t\tprintf(\"crytpodev type: AES-NI MB PMD\\n\"); break;\n+\tcase RTE_CRYPTODEV_QAT_PMD:\n+\t\tprintf(\"crytpodev type: QAT PMD\\n\"); break;\n+\t}\n+\n+\tprintf(\"sessionless crypto: %s\\n\",\n+\t\t\toptions->sessionless ? \"enabled\" : \"disabled\");\n+#if 0\n+\toptions->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;\n+\n+\t/* Cipher Data */\n+\toptions->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;\n+\toptions->cipher_xform.next = NULL;\n+\n+\toptions->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;\n+\toptions->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;\n+\n+\tgenerate_random_key(options->ckey_data, sizeof(options->ckey_data));\n+\n+\toptions->cipher_xform.cipher.key.data = options->ckey_data;\n+\toptions->cipher_xform.cipher.key.phys_addr = 0;\n+\toptions->cipher_xform.cipher.key.length = 16;\n+\n+\n+\t/* Authentication Data */\n+\toptions->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;\n+\toptions->auth_xform.next = NULL;\n+\n+\toptions->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;\n+\toptions->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;\n+\n+\toptions->auth_xform.auth.add_auth_data_length = 0;\n+\toptions->auth_xform.auth.digest_length = 20;\n+\n+\tgenerate_random_key(options->akey_data, sizeof(options->akey_data));\n+\n+\toptions->auth_xform.auth.key.data = options->akey_data;\n+\toptions->auth_xform.auth.key.phys_addr = 0;\n+\toptions->auth_xform.auth.key.length = 20;\n+#endif\n+}\n+\n+/* Parse the argument given in the command line of the application */\n+static int\n+l2fwd_crypto_parse_args(struct l2fwd_crypto_options *options,\n+\t\tint argc, char **argv)\n+{\n+\tint opt, retval, option_index;\n+\tchar **argvopt = argv, *prgname = argv[0];\n+\n+\tstatic struct option lgopts[] = {\n+\t\t\t{ \"no_stats\", no_argument, 0, 0 },\n+\t\t\t{ \"sessionless\", no_argument, 0, 0 },\n+\n+\t\t\t{ \"cdev_type\", required_argument, 0, 0 },\n+\t\t\t{ \"chain\", required_argument, 0, 0 },\n+\n+\t\t\t{ \"cipher_algo\", required_argument, 0, 0 },\n+\t\t\t{ \"cipher_op\", required_argument, 0, 0 },\n+\t\t\t{ \"cipher_key\", required_argument, 0, 0 },\n+\n+\t\t\t{ \"auth_algo\", required_argument, 0, 0 },\n+\t\t\t{ \"auth_op\", required_argument, 0, 0 },\n+\t\t\t{ \"auth_key\", required_argument, 0, 0 },\n+\n+\t\t\t{ \"iv\", required_argument, 0, 0 },\n+\n+\t\t\t{ \"sessionless\", no_argument, 0, 0 },\n+\t\t\t{ NULL, 0, 0, 0 }\n+\t};\n+\n+\tl2fwd_crypto_default_options(options);\n+\n+\twhile ((opt = getopt_long(argc, argvopt, \"p:q:st:\", lgopts,\n+\t\t\t&option_index)) != EOF) {\n+\t\tswitch (opt) {\n+\t\t/* long options */\n+\t\tcase 0:\n+\t\t\tretval = l2fwd_crypto_parse_args_long_options(options,\n+\t\t\t\t\tlgopts, option_index);\n+\t\t\tif (retval < 0) {\n+\t\t\t\tl2fwd_crypto_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t/* portmask */\n+\t\tcase 'p':\n+\t\t\tretval = l2fwd_crypto_parse_portmask(options, optarg);\n+\t\t\tif (retval < 0) {\n+\t\t\t\tl2fwd_crypto_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t/* nqueue */\n+\t\tcase 'q':\n+\t\t\tretval = l2fwd_crypto_parse_nqueue(options, optarg);\n+\t\t\tif (retval < 0) {\n+\t\t\t\tl2fwd_crypto_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t/* single lcore */\n+\t\tcase 's':\n+\t\t\tretval = l2fwd_crypto_parse_timer_period(options,\n+\t\t\t\t\toptarg);\n+\t\t\tif (retval < 0) {\n+\t\t\t\tl2fwd_crypto_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\t/* timer period */\n+\t\tcase 't':\n+\t\t\tretval = l2fwd_crypto_parse_timer_period(options,\n+\t\t\t\t\toptarg);\n+\t\t\tif (retval < 0) {\n+\t\t\t\tl2fwd_crypto_usage(prgname);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\tl2fwd_crypto_usage(prgname);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\n+\tif (optind >= 0)\n+\t\targv[optind-1] = prgname;\n+\n+\tretval = optind-1;\n+\toptind = 0; /* reset getopt lib */\n+\n+\treturn retval;\n+}\n+\n+/* Check the link status of all ports in up to 9s, and print them finally */\n+static void\n+check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)\n+{\n+#define CHECK_INTERVAL 100 /* 100ms */\n+#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */\n+\tuint8_t portid, count, all_ports_up, print_flag = 0;\n+\tstruct rte_eth_link link;\n+\n+\tprintf(\"\\nChecking link status\");\n+\tfflush(stdout);\n+\tfor (count = 0; count <= MAX_CHECK_TIME; count++) {\n+\t\tall_ports_up = 1;\n+\t\tfor (portid = 0; portid < port_num; portid++) {\n+\t\t\tif ((port_mask & (1 << portid)) == 0)\n+\t\t\t\tcontinue;\n+\t\t\tmemset(&link, 0, sizeof(link));\n+\t\t\trte_eth_link_get_nowait(portid, &link);\n+\t\t\t/* print link status if flag set */\n+\t\t\tif (print_flag == 1) {\n+\t\t\t\tif (link.link_status)\n+\t\t\t\t\tprintf(\"Port %d Link Up - speed %u \"\n+\t\t\t\t\t\t\"Mbps - %s\\n\", (uint8_t)portid,\n+\t\t\t\t\t\t(unsigned)link.link_speed,\n+\t\t\t\t(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?\n+\t\t\t\t\t(\"full-duplex\") : (\"half-duplex\\n\"));\n+\t\t\t\telse\n+\t\t\t\t\tprintf(\"Port %d Link Down\\n\",\n+\t\t\t\t\t\t(uint8_t)portid);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\t/* clear all_ports_up flag if any link down */\n+\t\t\tif (link.link_status == 0) {\n+\t\t\t\tall_ports_up = 0;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\t/* after finally printing all link status, get out */\n+\t\tif (print_flag == 1)\n+\t\t\tbreak;\n+\n+\t\tif (all_ports_up == 0) {\n+\t\t\tprintf(\".\");\n+\t\t\tfflush(stdout);\n+\t\t\trte_delay_ms(CHECK_INTERVAL);\n+\t\t}\n+\n+\t\t/* set the print_flag if all ports up or timeout */\n+\t\tif (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {\n+\t\t\tprint_flag = 1;\n+\t\t\tprintf(\"done\\n\");\n+\t\t}\n+\t}\n+}\n+\n+static int\n+initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports)\n+{\n+\tunsigned i, cdev_id, cdev_count, enabled_cdev_count = 0;\n+\tint retval;\n+\n+\tif (options->cdev_type == RTE_CRYPTODEV_QAT_PMD) {\n+\t\tif (rte_cryptodev_count() < nb_ports)\n+\t\t\treturn -1;\n+\t} else if (options->cdev_type == RTE_CRYPTODEV_AESNI_MB_PMD) {\n+\t\tfor (i = 0; i < nb_ports; i++) {\n+\t\t\tint id = rte_eal_vdev_init(CRYPTODEV_NAME_AESNI_MB_PMD,\n+\t\t\t\t\tNULL);\n+\t\t\tif (id < 0)\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tcdev_count = rte_cryptodev_count();\n+\tfor (cdev_id = 0;\n+\t\t\tcdev_id < cdev_count && enabled_cdev_count < nb_ports;\n+\t\t\tcdev_id++) {\n+\t\tstruct rte_cryptodev_qp_conf qp_conf;\n+\t\tstruct rte_cryptodev_info dev_info;\n+\n+\t\tstruct rte_cryptodev_config conf = {\n+\t\t\t.nb_queue_pairs = 1,\n+\t\t\t.socket_id = SOCKET_ID_ANY,\n+\t\t\t.session_mp = {\n+\t\t\t\t.nb_objs = 2048,\n+\t\t\t\t.cache_size = 64\n+\t\t\t}\n+\t\t};\n+\n+\t\trte_cryptodev_info_get(cdev_id, &dev_info);\n+\n+\t\tif (dev_info.dev_type != options->cdev_type)\n+\t\t\tcontinue;\n+\n+\n+\t\tretval = rte_cryptodev_configure(cdev_id, &conf);\n+\t\tif (retval < 0) {\n+\t\t\tprintf(\"Failed to configure cryptodev %u\", cdev_id);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tqp_conf.nb_descriptors = 2048;\n+\n+\t\tretval = rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,\n+\t\t\t\tSOCKET_ID_ANY);\n+\t\tif (retval < 0) {\n+\t\t\tprintf(\"Failed to setup queue pair %u on cryptodev %u\",\n+\t\t\t\t\t0, cdev_id);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tl2fwd_enabled_crypto_mask |= (1 << cdev_id);\n+\n+\t\tenabled_cdev_count++;\n+\t}\n+\n+\treturn enabled_cdev_count;\n+}\n+\n+static int\n+initialize_ports(struct l2fwd_crypto_options *options)\n+{\n+\tuint8_t last_portid, portid;\n+\tunsigned enabled_portcount = 0;\n+\tunsigned nb_ports = rte_eth_dev_count();\n+\n+\tif (nb_ports == 0) {\n+\t\tprintf(\"No Ethernet ports - bye\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tif (nb_ports > RTE_MAX_ETHPORTS)\n+\t\tnb_ports = RTE_MAX_ETHPORTS;\n+\n+\t/* Reset l2fwd_dst_ports */\n+\tfor (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)\n+\t\tl2fwd_dst_ports[portid] = 0;\n+\n+\tfor (last_portid = 0, portid = 0; portid < nb_ports; portid++) {\n+\t\tint retval;\n+\n+\t\t/* Skip ports that are not enabled */\n+\t\tif ((options->portmask & (1 << portid)) == 0)\n+\t\t\tcontinue;\n+\n+\t\t/* init port */\n+\t\tprintf(\"Initializing port %u... \", (unsigned) portid);\n+\t\tfflush(stdout);\n+\t\tretval = rte_eth_dev_configure(portid, 1, 1, &port_conf);\n+\t\tif (retval < 0) {\n+\t\t\tprintf(\"Cannot configure device: err=%d, port=%u\\n\",\n+\t\t\t\t  retval, (unsigned) portid);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* init one RX queue */\n+\t\tfflush(stdout);\n+\t\tretval = rte_eth_rx_queue_setup(portid, 0, nb_rxd,\n+\t\t\t\t\t     rte_eth_dev_socket_id(portid),\n+\t\t\t\t\t     NULL, l2fwd_pktmbuf_pool);\n+\t\tif (retval < 0) {\n+\t\t\tprintf(\"rte_eth_rx_queue_setup:err=%d, port=%u\\n\",\n+\t\t\t\t\tretval, (unsigned) portid);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* init one TX queue on each port */\n+\t\tfflush(stdout);\n+\t\tretval = rte_eth_tx_queue_setup(portid, 0, nb_txd,\n+\t\t\t\trte_eth_dev_socket_id(portid),\n+\t\t\t\tNULL);\n+\t\tif (retval < 0) {\n+\t\t\tprintf(\"rte_eth_tx_queue_setup:err=%d, port=%u\\n\",\n+\t\t\t\tretval, (unsigned) portid);\n+\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* Start device */\n+\t\tretval = rte_eth_dev_start(portid);\n+\t\tif (retval < 0) {\n+\t\t\tprintf(\"rte_eth_dev_start:err=%d, port=%u\\n\",\n+\t\t\t\t\tretval, (unsigned) portid);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\trte_eth_promiscuous_enable(portid);\n+\n+\t\trte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]);\n+\n+\t\tprintf(\"Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\\n\\n\",\n+\t\t\t\t(unsigned) portid,\n+\t\t\t\tl2fwd_ports_eth_addr[portid].addr_bytes[0],\n+\t\t\t\tl2fwd_ports_eth_addr[portid].addr_bytes[1],\n+\t\t\t\tl2fwd_ports_eth_addr[portid].addr_bytes[2],\n+\t\t\t\tl2fwd_ports_eth_addr[portid].addr_bytes[3],\n+\t\t\t\tl2fwd_ports_eth_addr[portid].addr_bytes[4],\n+\t\t\t\tl2fwd_ports_eth_addr[portid].addr_bytes[5]);\n+\n+\t\t/* initialize port stats */\n+\t\tmemset(&port_statistics, 0, sizeof(port_statistics));\n+\n+\t\t/* Setup port forwarding table */\n+\t\tif (enabled_portcount % 2) {\n+\t\t\tl2fwd_dst_ports[portid] = last_portid;\n+\t\t\tl2fwd_dst_ports[last_portid] = portid;\n+\t\t} else {\n+\t\t\tlast_portid = portid;\n+\t\t}\n+\n+\t\tl2fwd_enabled_port_mask |= (1 << portid);\n+\t\tenabled_portcount++;\n+\t}\n+\n+\tif (enabled_portcount == 1) {\n+\t\tl2fwd_dst_ports[last_portid] = last_portid;\n+\t} else if (enabled_portcount % 2) {\n+\t\tprintf(\"odd number of ports in portmask- bye\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tcheck_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);\n+\n+\treturn enabled_portcount;\n+}\n+\n+int\n+main(int argc, char **argv)\n+{\n+\tstruct lcore_queue_conf *qconf;\n+\tstruct l2fwd_crypto_options options;\n+\n+\tuint8_t nb_ports, nb_cryptodevs, portid, cdev_id;\n+\tunsigned lcore_id, rx_lcore_id;\n+\tint ret, enabled_cdevcount, enabled_portcount;\n+\n+\t/* init EAL */\n+\tret = rte_eal_init(argc, argv);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"Invalid EAL arguments\\n\");\n+\targc -= ret;\n+\targv += ret;\n+\n+\t/* parse application arguments (after the EAL ones) */\n+\tret = l2fwd_crypto_parse_args(&options, argc, argv);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"Invalid L2FWD-CRYPTO arguments\\n\");\n+\n+\t/* create the mbuf pool */\n+\tl2fwd_pktmbuf_pool = rte_pktmbuf_pool_create(\"mbuf_pool\", NB_MBUF, 128,\n+\t\t0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());\n+\tif (l2fwd_pktmbuf_pool == NULL)\n+\t\trte_exit(EXIT_FAILURE, \"Cannot create mbuf pool\\n\");\n+\n+\t/* create crypto op pool */\n+\tl2fwd_crtpto_op_pool = rte_crypto_op_pool_create(\"crypto_op_pool\",\n+\t\t\tNB_MBUF, 128, 2, rte_socket_id());\n+\tif (l2fwd_crtpto_op_pool == NULL)\n+\t\trte_exit(EXIT_FAILURE, \"Cannot create crypto op pool\\n\");\n+\n+\t/* Enable Ethernet ports */\n+\tenabled_portcount = initialize_ports(&options);\n+\tif (enabled_portcount < 1)\n+\t\trte_exit(EXIT_FAILURE, \"Failed to initial Ethernet ports\\n\");\n+\n+\tnb_ports = rte_eth_dev_count();\n+\t/* Initialize the port/queue configuration of each logical core */\n+\tfor (rx_lcore_id = 0, qconf = NULL, portid = 0;\n+\t\t\tportid < nb_ports; portid++) {\n+\n+\t\t/* skip ports that are not enabled */\n+\t\tif ((options.portmask & (1 << portid)) == 0)\n+\t\t\tcontinue;\n+\n+\t\tif (options.single_lcore && qconf == NULL) {\n+\t\t\twhile (rte_lcore_is_enabled(rx_lcore_id) == 0) {\n+\t\t\t\trx_lcore_id++;\n+\t\t\t\tif (rx_lcore_id >= RTE_MAX_LCORE)\n+\t\t\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\t\t\"Not enough cores\\n\");\n+\t\t\t}\n+\t\t} else if (!options.single_lcore) {\n+\t\t\t/* get the lcore_id for this port */\n+\t\t\twhile (rte_lcore_is_enabled(rx_lcore_id) == 0 ||\n+\t\t\t       lcore_queue_conf[rx_lcore_id].nb_rx_ports ==\n+\t\t\t       options.nb_ports_per_lcore) {\n+\t\t\t\trx_lcore_id++;\n+\t\t\t\tif (rx_lcore_id >= RTE_MAX_LCORE)\n+\t\t\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\t\t\"Not enough cores\\n\");\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Assigned a new logical core in the loop above. */\n+\t\tif (qconf != &lcore_queue_conf[rx_lcore_id])\n+\t\t\tqconf = &lcore_queue_conf[rx_lcore_id];\n+\n+\t\tqconf->rx_port_list[qconf->nb_rx_ports] = portid;\n+\t\tqconf->nb_rx_ports++;\n+\n+\t\tprintf(\"Lcore %u: RX port %u\\n\", rx_lcore_id, (unsigned)portid);\n+\t}\n+\n+\n+\t/* Enable Crypto devices */\n+\tenabled_cdevcount = initialize_cryptodevs(&options, enabled_portcount);\n+\tif (enabled_cdevcount < 1)\n+\t\trte_exit(EXIT_FAILURE, \"Failed to initial crypto devices\\n\");\n+\n+\tnb_cryptodevs = rte_cryptodev_count();\n+\t/* Initialize the port/queue configuration of each logical core */\n+\tfor (rx_lcore_id = 0, qconf = NULL, cdev_id = 0;\n+\t\t\tcdev_id < nb_cryptodevs && enabled_cdevcount;\n+\t\t\tcdev_id++) {\n+\t\tstruct rte_cryptodev_info info;\n+\n+\t\trte_cryptodev_info_get(cdev_id, &info);\n+\n+\t\t/* skip devices of the wrong type */\n+\t\tif (options.cdev_type != info.dev_type)\n+\t\t\tcontinue;\n+\n+\t\tif (options.single_lcore && qconf == NULL) {\n+\t\t\twhile (rte_lcore_is_enabled(rx_lcore_id) == 0) {\n+\t\t\t\trx_lcore_id++;\n+\t\t\t\tif (rx_lcore_id >= RTE_MAX_LCORE)\n+\t\t\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\t\t\"Not enough cores\\n\");\n+\t\t\t}\n+\t\t} else if (!options.single_lcore) {\n+\t\t\t/* get the lcore_id for this port */\n+\t\t\twhile (rte_lcore_is_enabled(rx_lcore_id) == 0 ||\n+\t\t\t       lcore_queue_conf[rx_lcore_id].nb_crypto_devs ==\n+\t\t\t       options.nb_ports_per_lcore) {\n+\t\t\t\trx_lcore_id++;\n+\t\t\t\tif (rx_lcore_id >= RTE_MAX_LCORE)\n+\t\t\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\t\t\"Not enough cores\\n\");\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Assigned a new logical core in the loop above. */\n+\t\tif (qconf != &lcore_queue_conf[rx_lcore_id])\n+\t\t\tqconf = &lcore_queue_conf[rx_lcore_id];\n+\n+\t\tqconf->cryptodev_list[qconf->nb_crypto_devs] = cdev_id;\n+\t\tqconf->nb_crypto_devs++;\n+\n+\t\tenabled_cdevcount--;\n+\n+\t\tprintf(\"Lcore %u: cryptodev %u\\n\", rx_lcore_id,\n+\t\t\t\t(unsigned)cdev_id);\n+\t}\n+\n+\n+\n+\t/* launch per-lcore init on every lcore */\n+\trte_eal_mp_remote_launch(l2fwd_launch_one_lcore, (void *)&options,\n+\t\t\tCALL_MASTER);\n+\tRTE_LCORE_FOREACH_SLAVE(lcore_id) {\n+\t\tif (rte_eal_wait_lcore(lcore_id) < 0)\n+\t\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n",
    "prefixes": [
        "dpdk-dev",
        "6/6"
    ]
}