get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 21419,
    "url": "https://patches.dpdk.org/api/patches/21419/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1488743225-25750-2-git-send-email-rkerur@gmail.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": "<1488743225-25750-2-git-send-email-rkerur@gmail.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1488743225-25750-2-git-send-email-rkerur@gmail.com",
    "date": "2017-03-05T19:47:03",
    "name": "[dpdk-dev,v4,1/3] Merge l3fwd-acl and l3fwd code.",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "13d15148342387d079fc4b7de2334e61ea9ab83c",
    "submitter": {
        "id": 134,
        "url": "https://patches.dpdk.org/api/people/134/?format=api",
        "name": "Ravi Kerur",
        "email": "rkerur@gmail.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1488743225-25750-2-git-send-email-rkerur@gmail.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/21419/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/21419/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 1D0D75927;\n\tSun,  5 Mar 2017 20:48:10 +0100 (CET)",
            "from mail-pg0-f67.google.com (mail-pg0-f67.google.com\n\t[74.125.83.67]) by dpdk.org (Postfix) with ESMTP id A9D0B2C74\n\tfor <dev@dpdk.org>; Sun,  5 Mar 2017 20:47:14 +0100 (CET)",
            "by mail-pg0-f67.google.com with SMTP id 187so4019260pgb.2\n\tfor <dev@dpdk.org>; Sun, 05 Mar 2017 11:47:14 -0800 (PST)",
            "from user-PC.hsd1.ca.comcast.net\n\t([2601:646:8680:32d0:9880:23bb:f0e5:b2da])\n\tby smtp.gmail.com with ESMTPSA id\n\tm6sm34876138pfg.126.2017.03.05.11.47.10\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tSun, 05 Mar 2017 11:47:10 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=yZLEbjwL9UQaxWNkxpQb05K473XTiagjCEHIYfAPQ/w=;\n\tb=bX4T9Z48Z0UDthbUZgxMFlPj/LKzIfoi6M+nozNUYO2u6B0Jc8sHEzy7HtRfxPjvn9\n\tMqKMkh8IH3E6IP/P64HcWADgKCBS2yGiPaZTD4lQmzIg2WgzWMr1li/9HuV3PEiUNkkE\n\tPyYi8rtta61x+vFjc7WMNtE8btt3SLDzFEH3zjn8LKY/Rz0vu23HK64cih/b2hy+Vq7b\n\txFo6XjcmAezrk0F3dgwl4W+Z8ghCjakla+P2cDWDK+erKDMuXFhLWFOg1KBxwcwyaEZG\n\tyAGPkBHMKKlSwFAfMWLLxddhd+TjUjgqcvrDttG+xYB52POuzDIxXKZyFBE1oHGIxhZ3\n\tbs2Q==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=yZLEbjwL9UQaxWNkxpQb05K473XTiagjCEHIYfAPQ/w=;\n\tb=Rr4lNc9U7w0784Cr9SNZ1KagA+JwsOB6mL5PL3xbG+DBEmPMsisEUr5MDp6tErokXP\n\tCFGHAdELipE7gw69sHPVG6awBdmkey4QmIDBQAY/etmKlQkG5kdjgN/I9yxUNaCh10rK\n\t4wrHd4XFON9U5qxi3J6vfkqckFl4hEw02vU4zym0OK9Sq1UKxX21JkzoegB2OioVwl4S\n\tU5RNfY3a4ZGP5o1nMUTpvQkVlQV8XoKvIAzzUJCqCyiIUmF43LsLNhhMV3tA96vAZ1bo\n\tvdFE8fUfGruMZx/3xX1L/BZlHBYKYx81HW2F9GacJeh/J9pB8Gf7quMHLhDQYsR9l8Lw\n\t83bg==",
        "X-Gm-Message-State": "AMke39nf00LykDgSaVD8uUzTPTLznCDYKQncbyuj4fJVRBhW1nE1fv5DMO86s7iAtjnbGw==",
        "X-Received": "by 10.98.54.196 with SMTP id d187mr16451197pfa.33.1488743231528; \n\tSun, 05 Mar 2017 11:47:11 -0800 (PST)",
        "From": "Ravi Kerur <rkerur@gmail.com>",
        "To": "dev@dpdk.org",
        "Cc": "konstantin.ananyev@intel.com, bruce.richardson@intel.com,\n\tRavi Kerur <rkerur@gmail.com>",
        "Date": "Sun,  5 Mar 2017 11:47:03 -0800",
        "Message-Id": "<1488743225-25750-2-git-send-email-rkerur@gmail.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1488743225-25750-1-git-send-email-rkerur@gmail.com>",
        "References": "<1488743225-25750-1-git-send-email-rkerur@gmail.com>",
        "Subject": "[dpdk-dev] [v4 1/3] Merge l3fwd-acl and l3fwd code.",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <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": "v4:\n\t> Initialize rss_hf to IP for LPM, EM and ACL.\n\t> Update rss_hf with l4 in parse_args for ACL.\n\t> Fix pending checkpatch code indentation warning.\n\nv3:\n\t> Fix additional checkpatch coding style issues.\n\nv2:\n\t> Fix checkpatch errors and warnings related to non strings\n\t\tgreater than 80 characters.\n\t> MACRO GET_CB_FIELD and strings greater than 80 characters\n\t\twarnings are not fixed.\n\nv1:\n\tl3fwd-acl changes:\n\t\t> Merge common init code in l3fwd-acl and l3fwd into\n\t\t\tmain.c.\n\t\t> Move non-critical inline functions to l3fwd_acl.h.\n\t\t> Move critial packet processing inline functions to\n\t\t\tl3fwd_acl_scalar.h\n\t\t> Move l3fwd-acl init code to l3fwd_acl.c.\n\t\t> Delete l3fwd-acl directory.\n\n\tl3fwd changes:\n\t\t> Add '-A' as an option for ACL processing.\n\t\t> Merge parsing options from l3fwd-acl and l3fwd. Retain\n\t\t\tl3fwd-acl definitions.\n\t\t> Move specific setup functions (setup_acl, setup_lpm\n\t\t\tand setup_hash).\n\tTesting:\n\t\t> Compiled successfully for x86_64-native-linuxapp-gcc\n\t\t\t> Tested LPM, EM and ACL basic functionality.\n\nSigned-off-by: Ravi Kerur <rkerur@gmail.com>\n---\n examples/l3fwd-acl/Makefile       |   56 -\n examples/l3fwd-acl/main.c         | 2079 -------------------------------------\n examples/l3fwd/Makefile           |    2 +-\n examples/l3fwd/l3fwd.h            |   49 +\n examples/l3fwd/l3fwd_acl.c        | 1064 +++++++++++++++++++\n examples/l3fwd/l3fwd_acl.h        |  263 +++++\n examples/l3fwd/l3fwd_acl_scalar.h |  182 ++++\n examples/l3fwd/l3fwd_em.c         |   14 +-\n examples/l3fwd/l3fwd_lpm.c        |   23 +-\n examples/l3fwd/main.c             |  209 ++--\n 10 files changed, 1722 insertions(+), 2219 deletions(-)\n delete mode 100644 examples/l3fwd-acl/Makefile\n delete mode 100644 examples/l3fwd-acl/main.c\n create mode 100644 examples/l3fwd/l3fwd_acl.c\n create mode 100644 examples/l3fwd/l3fwd_acl.h\n create mode 100644 examples/l3fwd/l3fwd_acl_scalar.h",
    "diff": "diff --git a/examples/l3fwd-acl/Makefile b/examples/l3fwd-acl/Makefile\ndeleted file mode 100644\nindex a3473a8..0000000\n--- a/examples/l3fwd-acl/Makefile\n+++ /dev/null\n@@ -1,56 +0,0 @@\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 overriden 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 = l3fwd-acl\n-\n-# all source are stored in SRCS-y\n-SRCS-y := main.c\n-\n-CFLAGS += -O3\n-CFLAGS += $(WERROR_FLAGS)\n-\n-# workaround for a gcc bug with noreturn attribute\n-# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603\n-ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)\n-CFLAGS_main.o += -Wno-return-type\n-endif\n-\n-include $(RTE_SDK)/mk/rte.extapp.mk\ndiff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c\ndeleted file mode 100644\nindex 3cfbb40..0000000\n--- a/examples/l3fwd-acl/main.c\n+++ /dev/null\n@@ -1,2079 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2016 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 <stdio.h>\n-#include <stdlib.h>\n-#include <stdint.h>\n-#include <inttypes.h>\n-#include <sys/types.h>\n-#include <string.h>\n-#include <sys/queue.h>\n-#include <stdarg.h>\n-#include <errno.h>\n-#include <getopt.h>\n-\n-#include <rte_common.h>\n-#include <rte_byteorder.h>\n-#include <rte_log.h>\n-#include <rte_memory.h>\n-#include <rte_memcpy.h>\n-#include <rte_memzone.h>\n-#include <rte_eal.h>\n-#include <rte_per_lcore.h>\n-#include <rte_launch.h>\n-#include <rte_atomic.h>\n-#include <rte_cycles.h>\n-#include <rte_prefetch.h>\n-#include <rte_lcore.h>\n-#include <rte_per_lcore.h>\n-#include <rte_branch_prediction.h>\n-#include <rte_interrupts.h>\n-#include <rte_pci.h>\n-#include <rte_random.h>\n-#include <rte_debug.h>\n-#include <rte_ether.h>\n-#include <rte_ethdev.h>\n-#include <rte_mempool.h>\n-#include <rte_mbuf.h>\n-#include <rte_ip.h>\n-#include <rte_tcp.h>\n-#include <rte_udp.h>\n-#include <rte_string_fns.h>\n-#include <rte_acl.h>\n-\n-#if RTE_LOG_LEVEL >= RTE_LOG_DEBUG\n-#define L3FWDACL_DEBUG\n-#endif\n-#define DO_RFC_1812_CHECKS\n-\n-#define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1\n-\n-#define MAX_JUMBO_PKT_LEN  9600\n-\n-#define MEMPOOL_CACHE_SIZE 256\n-\n-/*\n- * This expression is used to calculate the number of mbufs needed\n- * depending on user input, taking into account memory for rx and tx hardware\n- * rings, cache per lcore and mtable per port per lcore.\n- * RTE_MAX is used to ensure that NB_MBUF never goes below a\n- * minimum value of 8192\n- */\n-\n-#define NB_MBUF\tRTE_MAX(\\\n-\t(nb_ports * nb_rx_queue*RTE_TEST_RX_DESC_DEFAULT +\t\\\n-\tnb_ports * nb_lcores * MAX_PKT_BURST +\t\t\t\\\n-\tnb_ports * n_tx_queue * RTE_TEST_TX_DESC_DEFAULT +\t\\\n-\tnb_lcores * MEMPOOL_CACHE_SIZE),\t\t\t\\\n-\t(unsigned)8192)\n-\n-#define MAX_PKT_BURST 32\n-#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */\n-\n-#define NB_SOCKETS 8\n-\n-/* Configure how many packets ahead to prefetch, when reading packets */\n-#define PREFETCH_OFFSET\t3\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 ports_eth_addr[RTE_MAX_ETHPORTS];\n-\n-/* mask of enabled ports */\n-static uint32_t enabled_port_mask;\n-static int promiscuous_on; /**< Ports set in promiscuous mode off by default. */\n-static int numa_on = 1; /**< NUMA is enabled by default. */\n-\n-struct lcore_rx_queue {\n-\tuint8_t port_id;\n-\tuint8_t queue_id;\n-} __rte_cache_aligned;\n-\n-#define MAX_RX_QUEUE_PER_LCORE 16\n-#define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS\n-#define MAX_RX_QUEUE_PER_PORT 128\n-\n-#define MAX_LCORE_PARAMS 1024\n-struct lcore_params {\n-\tuint8_t port_id;\n-\tuint8_t queue_id;\n-\tuint8_t lcore_id;\n-} __rte_cache_aligned;\n-\n-static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS];\n-static struct lcore_params lcore_params_array_default[] = {\n-\t{0, 0, 2},\n-\t{0, 1, 2},\n-\t{0, 2, 2},\n-\t{1, 0, 2},\n-\t{1, 1, 2},\n-\t{1, 2, 2},\n-\t{2, 0, 2},\n-\t{3, 0, 3},\n-\t{3, 1, 3},\n-};\n-\n-static struct lcore_params *lcore_params = lcore_params_array_default;\n-static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) /\n-\t\t\t\tsizeof(lcore_params_array_default[0]);\n-\n-static struct rte_eth_conf port_conf = {\n-\t.rxmode = {\n-\t\t.mq_mode\t= ETH_MQ_RX_RSS,\n-\t\t.max_rx_pkt_len = ETHER_MAX_LEN,\n-\t\t.split_hdr_size = 0,\n-\t\t.header_split   = 0, /**< Header Split disabled */\n-\t\t.hw_ip_checksum = 1, /**< IP checksum offload enabled */\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.rx_adv_conf = {\n-\t\t.rss_conf = {\n-\t\t\t.rss_key = NULL,\n-\t\t\t.rss_hf = ETH_RSS_IP | ETH_RSS_UDP |\n-\t\t\t\tETH_RSS_TCP | ETH_RSS_SCTP,\n-\t\t},\n-\t},\n-\t.txmode = {\n-\t\t.mq_mode = ETH_MQ_TX_NONE,\n-\t},\n-};\n-\n-static struct rte_mempool *pktmbuf_pool[NB_SOCKETS];\n-\n-/***********************start of ACL part******************************/\n-#ifdef DO_RFC_1812_CHECKS\n-static inline int\n-is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len);\n-#endif\n-static inline void\n-send_single_packet(struct rte_mbuf *m, uint8_t port);\n-\n-#define MAX_ACL_RULE_NUM\t100000\n-#define DEFAULT_MAX_CATEGORIES\t1\n-#define L3FWD_ACL_IPV4_NAME\t\"l3fwd-acl-ipv4\"\n-#define L3FWD_ACL_IPV6_NAME\t\"l3fwd-acl-ipv6\"\n-#define ACL_LEAD_CHAR\t\t('@')\n-#define ROUTE_LEAD_CHAR\t\t('R')\n-#define COMMENT_LEAD_CHAR\t('#')\n-#define OPTION_CONFIG\t\t\"config\"\n-#define OPTION_NONUMA\t\t\"no-numa\"\n-#define OPTION_ENBJMO\t\t\"enable-jumbo\"\n-#define OPTION_RULE_IPV4\t\"rule_ipv4\"\n-#define OPTION_RULE_IPV6\t\"rule_ipv6\"\n-#define OPTION_SCALAR\t\t\"scalar\"\n-#define ACL_DENY_SIGNATURE\t0xf0000000\n-#define RTE_LOGTYPE_L3FWDACL\tRTE_LOGTYPE_USER3\n-#define acl_log(format, ...)\tRTE_LOG(ERR, L3FWDACL, format, ##__VA_ARGS__)\n-#define uint32_t_to_char(ip, a, b, c, d) do {\\\n-\t\t*a = (unsigned char)(ip >> 24 & 0xff);\\\n-\t\t*b = (unsigned char)(ip >> 16 & 0xff);\\\n-\t\t*c = (unsigned char)(ip >> 8 & 0xff);\\\n-\t\t*d = (unsigned char)(ip & 0xff);\\\n-\t} while (0)\n-#define OFF_ETHHEAD\t(sizeof(struct ether_hdr))\n-#define OFF_IPV42PROTO (offsetof(struct ipv4_hdr, next_proto_id))\n-#define OFF_IPV62PROTO (offsetof(struct ipv6_hdr, proto))\n-#define MBUF_IPV4_2PROTO(m)\t\\\n-\trte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV42PROTO)\n-#define MBUF_IPV6_2PROTO(m)\t\\\n-\trte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV62PROTO)\n-\n-#define GET_CB_FIELD(in, fd, base, lim, dlm)\tdo {            \\\n-\tunsigned long val;                                      \\\n-\tchar *end;                                              \\\n-\terrno = 0;                                              \\\n-\tval = strtoul((in), &end, (base));                      \\\n-\tif (errno != 0 || end[0] != (dlm) || val > (lim))       \\\n-\t\treturn -EINVAL;                               \\\n-\t(fd) = (typeof(fd))val;                                 \\\n-\t(in) = end + 1;                                         \\\n-} while (0)\n-\n-/*\n-  * ACL rules should have higher priorities than route ones to ensure ACL rule\n-  * always be found when input packets have multi-matches in the database.\n-  * A exception case is performance measure, which can define route rules with\n-  * higher priority and route rules will always be returned in each lookup.\n-  * Reserve range from ACL_RULE_PRIORITY_MAX + 1 to\n-  * RTE_ACL_MAX_PRIORITY for route entries in performance measure\n-  */\n-#define ACL_RULE_PRIORITY_MAX 0x10000000\n-\n-/*\n-  * Forward port info save in ACL lib starts from 1\n-  * since ACL assume 0 is invalid.\n-  * So, need add 1 when saving and minus 1 when forwarding packets.\n-  */\n-#define FWD_PORT_SHIFT 1\n-\n-/*\n- * Rule and trace formats definitions.\n- */\n-\n-enum {\n-\tPROTO_FIELD_IPV4,\n-\tSRC_FIELD_IPV4,\n-\tDST_FIELD_IPV4,\n-\tSRCP_FIELD_IPV4,\n-\tDSTP_FIELD_IPV4,\n-\tNUM_FIELDS_IPV4\n-};\n-\n-/*\n- * That effectively defines order of IPV4VLAN classifications:\n- *  - PROTO\n- *  - VLAN (TAG and DOMAIN)\n- *  - SRC IP ADDRESS\n- *  - DST IP ADDRESS\n- *  - PORTS (SRC and DST)\n- */\n-enum {\n-\tRTE_ACL_IPV4VLAN_PROTO,\n-\tRTE_ACL_IPV4VLAN_VLAN,\n-\tRTE_ACL_IPV4VLAN_SRC,\n-\tRTE_ACL_IPV4VLAN_DST,\n-\tRTE_ACL_IPV4VLAN_PORTS,\n-\tRTE_ACL_IPV4VLAN_NUM\n-};\n-\n-struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_BITMASK,\n-\t\t.size = sizeof(uint8_t),\n-\t\t.field_index = PROTO_FIELD_IPV4,\n-\t\t.input_index = RTE_ACL_IPV4VLAN_PROTO,\n-\t\t.offset = 0,\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = SRC_FIELD_IPV4,\n-\t\t.input_index = RTE_ACL_IPV4VLAN_SRC,\n-\t\t.offset = offsetof(struct ipv4_hdr, src_addr) -\n-\t\t\toffsetof(struct ipv4_hdr, next_proto_id),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = DST_FIELD_IPV4,\n-\t\t.input_index = RTE_ACL_IPV4VLAN_DST,\n-\t\t.offset = offsetof(struct ipv4_hdr, dst_addr) -\n-\t\t\toffsetof(struct ipv4_hdr, next_proto_id),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_RANGE,\n-\t\t.size = sizeof(uint16_t),\n-\t\t.field_index = SRCP_FIELD_IPV4,\n-\t\t.input_index = RTE_ACL_IPV4VLAN_PORTS,\n-\t\t.offset = sizeof(struct ipv4_hdr) -\n-\t\t\toffsetof(struct ipv4_hdr, next_proto_id),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_RANGE,\n-\t\t.size = sizeof(uint16_t),\n-\t\t.field_index = DSTP_FIELD_IPV4,\n-\t\t.input_index = RTE_ACL_IPV4VLAN_PORTS,\n-\t\t.offset = sizeof(struct ipv4_hdr) -\n-\t\t\toffsetof(struct ipv4_hdr, next_proto_id) +\n-\t\t\tsizeof(uint16_t),\n-\t},\n-};\n-\n-#define\tIPV6_ADDR_LEN\t16\n-#define\tIPV6_ADDR_U16\t(IPV6_ADDR_LEN / sizeof(uint16_t))\n-#define\tIPV6_ADDR_U32\t(IPV6_ADDR_LEN / sizeof(uint32_t))\n-\n-enum {\n-\tPROTO_FIELD_IPV6,\n-\tSRC1_FIELD_IPV6,\n-\tSRC2_FIELD_IPV6,\n-\tSRC3_FIELD_IPV6,\n-\tSRC4_FIELD_IPV6,\n-\tDST1_FIELD_IPV6,\n-\tDST2_FIELD_IPV6,\n-\tDST3_FIELD_IPV6,\n-\tDST4_FIELD_IPV6,\n-\tSRCP_FIELD_IPV6,\n-\tDSTP_FIELD_IPV6,\n-\tNUM_FIELDS_IPV6\n-};\n-\n-struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = {\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_BITMASK,\n-\t\t.size = sizeof(uint8_t),\n-\t\t.field_index = PROTO_FIELD_IPV6,\n-\t\t.input_index = PROTO_FIELD_IPV6,\n-\t\t.offset = 0,\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = SRC1_FIELD_IPV6,\n-\t\t.input_index = SRC1_FIELD_IPV6,\n-\t\t.offset = offsetof(struct ipv6_hdr, src_addr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = SRC2_FIELD_IPV6,\n-\t\t.input_index = SRC2_FIELD_IPV6,\n-\t\t.offset = offsetof(struct ipv6_hdr, src_addr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto) + sizeof(uint32_t),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = SRC3_FIELD_IPV6,\n-\t\t.input_index = SRC3_FIELD_IPV6,\n-\t\t.offset = offsetof(struct ipv6_hdr, src_addr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto) + 2 * sizeof(uint32_t),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = SRC4_FIELD_IPV6,\n-\t\t.input_index = SRC4_FIELD_IPV6,\n-\t\t.offset = offsetof(struct ipv6_hdr, src_addr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto) + 3 * sizeof(uint32_t),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = DST1_FIELD_IPV6,\n-\t\t.input_index = DST1_FIELD_IPV6,\n-\t\t.offset = offsetof(struct ipv6_hdr, dst_addr)\n-\t\t\t\t- offsetof(struct ipv6_hdr, proto),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = DST2_FIELD_IPV6,\n-\t\t.input_index = DST2_FIELD_IPV6,\n-\t\t.offset = offsetof(struct ipv6_hdr, dst_addr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto) + sizeof(uint32_t),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = DST3_FIELD_IPV6,\n-\t\t.input_index = DST3_FIELD_IPV6,\n-\t\t.offset = offsetof(struct ipv6_hdr, dst_addr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto) + 2 * sizeof(uint32_t),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n-\t\t.size = sizeof(uint32_t),\n-\t\t.field_index = DST4_FIELD_IPV6,\n-\t\t.input_index = DST4_FIELD_IPV6,\n-\t\t.offset = offsetof(struct ipv6_hdr, dst_addr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto) + 3 * sizeof(uint32_t),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_RANGE,\n-\t\t.size = sizeof(uint16_t),\n-\t\t.field_index = SRCP_FIELD_IPV6,\n-\t\t.input_index = SRCP_FIELD_IPV6,\n-\t\t.offset = sizeof(struct ipv6_hdr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto),\n-\t},\n-\t{\n-\t\t.type = RTE_ACL_FIELD_TYPE_RANGE,\n-\t\t.size = sizeof(uint16_t),\n-\t\t.field_index = DSTP_FIELD_IPV6,\n-\t\t.input_index = SRCP_FIELD_IPV6,\n-\t\t.offset = sizeof(struct ipv6_hdr) -\n-\t\t\toffsetof(struct ipv6_hdr, proto) + sizeof(uint16_t),\n-\t},\n-};\n-\n-enum {\n-\tCB_FLD_SRC_ADDR,\n-\tCB_FLD_DST_ADDR,\n-\tCB_FLD_SRC_PORT_LOW,\n-\tCB_FLD_SRC_PORT_DLM,\n-\tCB_FLD_SRC_PORT_HIGH,\n-\tCB_FLD_DST_PORT_LOW,\n-\tCB_FLD_DST_PORT_DLM,\n-\tCB_FLD_DST_PORT_HIGH,\n-\tCB_FLD_PROTO,\n-\tCB_FLD_USERDATA,\n-\tCB_FLD_NUM,\n-};\n-\n-RTE_ACL_RULE_DEF(acl4_rule, RTE_DIM(ipv4_defs));\n-RTE_ACL_RULE_DEF(acl6_rule, RTE_DIM(ipv6_defs));\n-\n-struct acl_search_t {\n-\tconst uint8_t *data_ipv4[MAX_PKT_BURST];\n-\tstruct rte_mbuf *m_ipv4[MAX_PKT_BURST];\n-\tuint32_t res_ipv4[MAX_PKT_BURST];\n-\tint num_ipv4;\n-\n-\tconst uint8_t *data_ipv6[MAX_PKT_BURST];\n-\tstruct rte_mbuf *m_ipv6[MAX_PKT_BURST];\n-\tuint32_t res_ipv6[MAX_PKT_BURST];\n-\tint num_ipv6;\n-};\n-\n-static struct {\n-\tchar mapped[NB_SOCKETS];\n-\tstruct rte_acl_ctx *acx_ipv4[NB_SOCKETS];\n-\tstruct rte_acl_ctx *acx_ipv6[NB_SOCKETS];\n-#ifdef L3FWDACL_DEBUG\n-\tstruct acl4_rule *rule_ipv4;\n-\tstruct acl6_rule *rule_ipv6;\n-#endif\n-} acl_config;\n-\n-static struct{\n-\tconst char *rule_ipv4_name;\n-\tconst char *rule_ipv6_name;\n-\tint scalar;\n-} parm_config;\n-\n-const char cb_port_delim[] = \":\";\n-\n-static inline void\n-print_one_ipv4_rule(struct acl4_rule *rule, int extra)\n-{\n-\tunsigned char a, b, c, d;\n-\n-\tuint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32,\n-\t\t\t&a, &b, &c, &d);\n-\tprintf(\"%hhu.%hhu.%hhu.%hhu/%u \", a, b, c, d,\n-\t\t\trule->field[SRC_FIELD_IPV4].mask_range.u32);\n-\tuint32_t_to_char(rule->field[DST_FIELD_IPV4].value.u32,\n-\t\t\t&a, &b, &c, &d);\n-\tprintf(\"%hhu.%hhu.%hhu.%hhu/%u \", a, b, c, d,\n-\t\t\trule->field[DST_FIELD_IPV4].mask_range.u32);\n-\tprintf(\"%hu : %hu %hu : %hu 0x%hhx/0x%hhx \",\n-\t\trule->field[SRCP_FIELD_IPV4].value.u16,\n-\t\trule->field[SRCP_FIELD_IPV4].mask_range.u16,\n-\t\trule->field[DSTP_FIELD_IPV4].value.u16,\n-\t\trule->field[DSTP_FIELD_IPV4].mask_range.u16,\n-\t\trule->field[PROTO_FIELD_IPV4].value.u8,\n-\t\trule->field[PROTO_FIELD_IPV4].mask_range.u8);\n-\tif (extra)\n-\t\tprintf(\"0x%x-0x%x-0x%x \",\n-\t\t\trule->data.category_mask,\n-\t\t\trule->data.priority,\n-\t\t\trule->data.userdata);\n-}\n-\n-static inline void\n-print_one_ipv6_rule(struct acl6_rule *rule, int extra)\n-{\n-\tunsigned char a, b, c, d;\n-\n-\tuint32_t_to_char(rule->field[SRC1_FIELD_IPV6].value.u32,\n-\t\t&a, &b, &c, &d);\n-\tprintf(\"%.2x%.2x:%.2x%.2x\", a, b, c, d);\n-\tuint32_t_to_char(rule->field[SRC2_FIELD_IPV6].value.u32,\n-\t\t&a, &b, &c, &d);\n-\tprintf(\":%.2x%.2x:%.2x%.2x\", a, b, c, d);\n-\tuint32_t_to_char(rule->field[SRC3_FIELD_IPV6].value.u32,\n-\t\t&a, &b, &c, &d);\n-\tprintf(\":%.2x%.2x:%.2x%.2x\", a, b, c, d);\n-\tuint32_t_to_char(rule->field[SRC4_FIELD_IPV6].value.u32,\n-\t\t&a, &b, &c, &d);\n-\tprintf(\":%.2x%.2x:%.2x%.2x/%u \", a, b, c, d,\n-\t\t\trule->field[SRC1_FIELD_IPV6].mask_range.u32\n-\t\t\t+ rule->field[SRC2_FIELD_IPV6].mask_range.u32\n-\t\t\t+ rule->field[SRC3_FIELD_IPV6].mask_range.u32\n-\t\t\t+ rule->field[SRC4_FIELD_IPV6].mask_range.u32);\n-\n-\tuint32_t_to_char(rule->field[DST1_FIELD_IPV6].value.u32,\n-\t\t&a, &b, &c, &d);\n-\tprintf(\"%.2x%.2x:%.2x%.2x\", a, b, c, d);\n-\tuint32_t_to_char(rule->field[DST2_FIELD_IPV6].value.u32,\n-\t\t&a, &b, &c, &d);\n-\tprintf(\":%.2x%.2x:%.2x%.2x\", a, b, c, d);\n-\tuint32_t_to_char(rule->field[DST3_FIELD_IPV6].value.u32,\n-\t\t&a, &b, &c, &d);\n-\tprintf(\":%.2x%.2x:%.2x%.2x\", a, b, c, d);\n-\tuint32_t_to_char(rule->field[DST4_FIELD_IPV6].value.u32,\n-\t\t&a, &b, &c, &d);\n-\tprintf(\":%.2x%.2x:%.2x%.2x/%u \", a, b, c, d,\n-\t\t\trule->field[DST1_FIELD_IPV6].mask_range.u32\n-\t\t\t+ rule->field[DST2_FIELD_IPV6].mask_range.u32\n-\t\t\t+ rule->field[DST3_FIELD_IPV6].mask_range.u32\n-\t\t\t+ rule->field[DST4_FIELD_IPV6].mask_range.u32);\n-\n-\tprintf(\"%hu : %hu %hu : %hu 0x%hhx/0x%hhx \",\n-\t\trule->field[SRCP_FIELD_IPV6].value.u16,\n-\t\trule->field[SRCP_FIELD_IPV6].mask_range.u16,\n-\t\trule->field[DSTP_FIELD_IPV6].value.u16,\n-\t\trule->field[DSTP_FIELD_IPV6].mask_range.u16,\n-\t\trule->field[PROTO_FIELD_IPV6].value.u8,\n-\t\trule->field[PROTO_FIELD_IPV6].mask_range.u8);\n-\tif (extra)\n-\t\tprintf(\"0x%x-0x%x-0x%x \",\n-\t\t\trule->data.category_mask,\n-\t\t\trule->data.priority,\n-\t\t\trule->data.userdata);\n-}\n-\n-/* Bypass comment and empty lines */\n-static inline int\n-is_bypass_line(char *buff)\n-{\n-\tint i = 0;\n-\n-\t/* comment line */\n-\tif (buff[0] == COMMENT_LEAD_CHAR)\n-\t\treturn 1;\n-\t/* empty line */\n-\twhile (buff[i] != '\\0') {\n-\t\tif (!isspace(buff[i]))\n-\t\t\treturn 0;\n-\t\ti++;\n-\t}\n-\treturn 1;\n-}\n-\n-#ifdef L3FWDACL_DEBUG\n-static inline void\n-dump_acl4_rule(struct rte_mbuf *m, uint32_t sig)\n-{\n-\tuint32_t offset = sig & ~ACL_DENY_SIGNATURE;\n-\tunsigned char a, b, c, d;\n-\tstruct ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset(m,\n-\t\t\t\t\t\t\t    struct ipv4_hdr *,\n-\t\t\t\t\t\t\t    sizeof(struct ether_hdr));\n-\n-\tuint32_t_to_char(rte_bswap32(ipv4_hdr->src_addr), &a, &b, &c, &d);\n-\tprintf(\"Packet Src:%hhu.%hhu.%hhu.%hhu \", a, b, c, d);\n-\tuint32_t_to_char(rte_bswap32(ipv4_hdr->dst_addr), &a, &b, &c, &d);\n-\tprintf(\"Dst:%hhu.%hhu.%hhu.%hhu \", a, b, c, d);\n-\n-\tprintf(\"Src port:%hu,Dst port:%hu \",\n-\t\t\trte_bswap16(*(uint16_t *)(ipv4_hdr + 1)),\n-\t\t\trte_bswap16(*((uint16_t *)(ipv4_hdr + 1) + 1)));\n-\tprintf(\"hit ACL %d - \", offset);\n-\n-\tprint_one_ipv4_rule(acl_config.rule_ipv4 + offset, 1);\n-\n-\tprintf(\"\\n\\n\");\n-}\n-\n-static inline void\n-dump_acl6_rule(struct rte_mbuf *m, uint32_t sig)\n-{\n-\tunsigned i;\n-\tuint32_t offset = sig & ~ACL_DENY_SIGNATURE;\n-\tstruct ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset(m,\n-\t\t\t\t\t\t\t    struct ipv6_hdr *,\n-\t\t\t\t\t\t\t    sizeof(struct ether_hdr));\n-\n-\tprintf(\"Packet Src\");\n-\tfor (i = 0; i < RTE_DIM(ipv6_hdr->src_addr); i += sizeof(uint16_t))\n-\t\tprintf(\":%.2x%.2x\",\n-\t\t\tipv6_hdr->src_addr[i], ipv6_hdr->src_addr[i + 1]);\n-\n-\tprintf(\"\\nDst\");\n-\tfor (i = 0; i < RTE_DIM(ipv6_hdr->dst_addr); i += sizeof(uint16_t))\n-\t\tprintf(\":%.2x%.2x\",\n-\t\t\tipv6_hdr->dst_addr[i], ipv6_hdr->dst_addr[i + 1]);\n-\n-\tprintf(\"\\nSrc port:%hu,Dst port:%hu \",\n-\t\t\trte_bswap16(*(uint16_t *)(ipv6_hdr + 1)),\n-\t\t\trte_bswap16(*((uint16_t *)(ipv6_hdr + 1) + 1)));\n-\tprintf(\"hit ACL %d - \", offset);\n-\n-\tprint_one_ipv6_rule(acl_config.rule_ipv6 + offset, 1);\n-\n-\tprintf(\"\\n\\n\");\n-}\n-#endif /* L3FWDACL_DEBUG */\n-\n-static inline void\n-dump_ipv4_rules(struct acl4_rule *rule, int num, int extra)\n-{\n-\tint i;\n-\n-\tfor (i = 0; i < num; i++, rule++) {\n-\t\tprintf(\"\\t%d:\", i + 1);\n-\t\tprint_one_ipv4_rule(rule, extra);\n-\t\tprintf(\"\\n\");\n-\t}\n-}\n-\n-static inline void\n-dump_ipv6_rules(struct acl6_rule *rule, int num, int extra)\n-{\n-\tint i;\n-\n-\tfor (i = 0; i < num; i++, rule++) {\n-\t\tprintf(\"\\t%d:\", i + 1);\n-\t\tprint_one_ipv6_rule(rule, extra);\n-\t\tprintf(\"\\n\");\n-\t}\n-}\n-\n-#ifdef DO_RFC_1812_CHECKS\n-static inline void\n-prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,\n-\tint index)\n-{\n-\tstruct ipv4_hdr *ipv4_hdr;\n-\tstruct rte_mbuf *pkt = pkts_in[index];\n-\n-\tif (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {\n-\t\tipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct ipv4_hdr *,\n-\t\t\t\t\t\t   sizeof(struct ether_hdr));\n-\n-\t\t/* Check to make sure the packet is valid (RFC1812) */\n-\t\tif (is_valid_ipv4_pkt(ipv4_hdr, pkt->pkt_len) >= 0) {\n-\n-\t\t\t/* Update time to live and header checksum */\n-\t\t\t--(ipv4_hdr->time_to_live);\n-\t\t\t++(ipv4_hdr->hdr_checksum);\n-\n-\t\t\t/* Fill acl structure */\n-\t\t\tacl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);\n-\t\t\tacl->m_ipv4[(acl->num_ipv4)++] = pkt;\n-\n-\t\t} else {\n-\t\t\t/* Not a valid IPv4 packet */\n-\t\t\trte_pktmbuf_free(pkt);\n-\t\t}\n-\t} else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {\n-\t\t/* Fill acl structure */\n-\t\tacl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);\n-\t\tacl->m_ipv6[(acl->num_ipv6)++] = pkt;\n-\n-\t} else {\n-\t\t/* Unknown type, drop the packet */\n-\t\trte_pktmbuf_free(pkt);\n-\t}\n-}\n-\n-#else\n-static inline void\n-prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,\n-\tint index)\n-{\n-\tstruct rte_mbuf *pkt = pkts_in[index];\n-\n-\tif (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {\n-\t\t/* Fill acl structure */\n-\t\tacl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);\n-\t\tacl->m_ipv4[(acl->num_ipv4)++] = pkt;\n-\n-\t} else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {\n-\t\t/* Fill acl structure */\n-\t\tacl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);\n-\t\tacl->m_ipv6[(acl->num_ipv6)++] = pkt;\n-\t} else {\n-\t\t/* Unknown type, drop the packet */\n-\t\trte_pktmbuf_free(pkt);\n-\t}\n-}\n-#endif /* DO_RFC_1812_CHECKS */\n-\n-static inline void\n-prepare_acl_parameter(struct rte_mbuf **pkts_in, struct acl_search_t *acl,\n-\tint nb_rx)\n-{\n-\tint i;\n-\n-\tacl->num_ipv4 = 0;\n-\tacl->num_ipv6 = 0;\n-\n-\t/* Prefetch first packets */\n-\tfor (i = 0; i < PREFETCH_OFFSET && i < nb_rx; i++) {\n-\t\trte_prefetch0(rte_pktmbuf_mtod(\n-\t\t\t\tpkts_in[i], void *));\n-\t}\n-\n-\tfor (i = 0; i < (nb_rx - PREFETCH_OFFSET); i++) {\n-\t\trte_prefetch0(rte_pktmbuf_mtod(pkts_in[\n-\t\t\t\ti + PREFETCH_OFFSET], void *));\n-\t\tprepare_one_packet(pkts_in, acl, i);\n-\t}\n-\n-\t/* Process left packets */\n-\tfor (; i < nb_rx; i++)\n-\t\tprepare_one_packet(pkts_in, acl, i);\n-}\n-\n-static inline void\n-send_one_packet(struct rte_mbuf *m, uint32_t res)\n-{\n-\tif (likely((res & ACL_DENY_SIGNATURE) == 0 && res != 0)) {\n-\t\t/* forward packets */\n-\t\tsend_single_packet(m,\n-\t\t\t(uint8_t)(res - FWD_PORT_SHIFT));\n-\t} else{\n-\t\t/* in the ACL list, drop it */\n-#ifdef L3FWDACL_DEBUG\n-\t\tif ((res & ACL_DENY_SIGNATURE) != 0) {\n-\t\t\tif (RTE_ETH_IS_IPV4_HDR(m->packet_type))\n-\t\t\t\tdump_acl4_rule(m, res);\n-\t\t\telse if (RTE_ETH_IS_IPV6_HDR(m->packet_type))\n-\t\t\t\tdump_acl6_rule(m, res);\n-\t\t}\n-#endif\n-\t\trte_pktmbuf_free(m);\n-\t}\n-}\n-\n-\n-\n-static inline void\n-send_packets(struct rte_mbuf **m, uint32_t *res, int num)\n-{\n-\tint i;\n-\n-\t/* Prefetch first packets */\n-\tfor (i = 0; i < PREFETCH_OFFSET && i < num; i++) {\n-\t\trte_prefetch0(rte_pktmbuf_mtod(\n-\t\t\t\tm[i], void *));\n-\t}\n-\n-\tfor (i = 0; i < (num - PREFETCH_OFFSET); i++) {\n-\t\trte_prefetch0(rte_pktmbuf_mtod(m[\n-\t\t\t\ti + PREFETCH_OFFSET], void *));\n-\t\tsend_one_packet(m[i], res[i]);\n-\t}\n-\n-\t/* Process left packets */\n-\tfor (; i < num; i++)\n-\t\tsend_one_packet(m[i], res[i]);\n-}\n-\n-/*\n- * Parses IPV6 address, exepcts the following format:\n- * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is a hexedecimal digit).\n- */\n-static int\n-parse_ipv6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32],\n-\tchar dlm)\n-{\n-\tuint32_t addr[IPV6_ADDR_U16];\n-\n-\tGET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':');\n-\tGET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':');\n-\tGET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':');\n-\tGET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':');\n-\tGET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':');\n-\tGET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':');\n-\tGET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':');\n-\tGET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm);\n-\n-\t*end = in;\n-\n-\tv[0] = (addr[0] << 16) + addr[1];\n-\tv[1] = (addr[2] << 16) + addr[3];\n-\tv[2] = (addr[4] << 16) + addr[5];\n-\tv[3] = (addr[6] << 16) + addr[7];\n-\n-\treturn 0;\n-}\n-\n-static int\n-parse_ipv6_net(const char *in, struct rte_acl_field field[4])\n-{\n-\tint32_t rc;\n-\tconst char *mp;\n-\tuint32_t i, m, v[4];\n-\tconst uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT;\n-\n-\t/* get address. */\n-\trc = parse_ipv6_addr(in, &mp, v, '/');\n-\tif (rc != 0)\n-\t\treturn rc;\n-\n-\t/* get mask. */\n-\tGET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0);\n-\n-\t/* put all together. */\n-\tfor (i = 0; i != RTE_DIM(v); i++) {\n-\t\tif (m >= (i + 1) * nbu32)\n-\t\t\tfield[i].mask_range.u32 = nbu32;\n-\t\telse\n-\t\t\tfield[i].mask_range.u32 = m > (i * nbu32) ?\n-\t\t\t\tm - (i * 32) : 0;\n-\n-\t\tfield[i].value.u32 = v[i];\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int\n-parse_cb_ipv6_rule(char *str, struct rte_acl_rule *v, int has_userdata)\n-{\n-\tint i, rc;\n-\tchar *s, *sp, *in[CB_FLD_NUM];\n-\tstatic const char *dlm = \" \\t\\n\";\n-\tint dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA;\n-\ts = str;\n-\n-\tfor (i = 0; i != dim; i++, s = NULL) {\n-\t\tin[i] = strtok_r(s, dlm, &sp);\n-\t\tif (in[i] == NULL)\n-\t\t\treturn -EINVAL;\n-\t}\n-\n-\trc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6);\n-\tif (rc != 0) {\n-\t\tacl_log(\"failed to read source address/mask: %s\\n\",\n-\t\t\tin[CB_FLD_SRC_ADDR]);\n-\t\treturn rc;\n-\t}\n-\n-\trc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6);\n-\tif (rc != 0) {\n-\t\tacl_log(\"failed to read destination address/mask: %s\\n\",\n-\t\t\tin[CB_FLD_DST_ADDR]);\n-\t\treturn rc;\n-\t}\n-\n-\t/* source port. */\n-\tGET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],\n-\t\tv->field[SRCP_FIELD_IPV6].value.u16,\n-\t\t0, UINT16_MAX, 0);\n-\tGET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],\n-\t\tv->field[SRCP_FIELD_IPV6].mask_range.u16,\n-\t\t0, UINT16_MAX, 0);\n-\n-\tif (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,\n-\t\t\tsizeof(cb_port_delim)) != 0)\n-\t\treturn -EINVAL;\n-\n-\t/* destination port. */\n-\tGET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],\n-\t\tv->field[DSTP_FIELD_IPV6].value.u16,\n-\t\t0, UINT16_MAX, 0);\n-\tGET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],\n-\t\tv->field[DSTP_FIELD_IPV6].mask_range.u16,\n-\t\t0, UINT16_MAX, 0);\n-\n-\tif (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,\n-\t\t\tsizeof(cb_port_delim)) != 0)\n-\t\treturn -EINVAL;\n-\n-\tif (v->field[SRCP_FIELD_IPV6].mask_range.u16\n-\t\t\t< v->field[SRCP_FIELD_IPV6].value.u16\n-\t\t\t|| v->field[DSTP_FIELD_IPV6].mask_range.u16\n-\t\t\t< v->field[DSTP_FIELD_IPV6].value.u16)\n-\t\treturn -EINVAL;\n-\n-\tGET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8,\n-\t\t0, UINT8_MAX, '/');\n-\tGET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8,\n-\t\t0, UINT8_MAX, 0);\n-\n-\tif (has_userdata)\n-\t\tGET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata,\n-\t\t\t0, UINT32_MAX, 0);\n-\n-\treturn 0;\n-}\n-\n-/*\n- * Parse ClassBench rules file.\n- * Expected format:\n- * '@'<src_ipv4_addr>'/'<masklen> <space> \\\n- * <dst_ipv4_addr>'/'<masklen> <space> \\\n- * <src_port_low> <space> \":\" <src_port_high> <space> \\\n- * <dst_port_low> <space> \":\" <dst_port_high> <space> \\\n- * <proto>'/'<mask>\n- */\n-static int\n-parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)\n-{\n-\tuint8_t a, b, c, d, m;\n-\n-\tGET_CB_FIELD(in, a, 0, UINT8_MAX, '.');\n-\tGET_CB_FIELD(in, b, 0, UINT8_MAX, '.');\n-\tGET_CB_FIELD(in, c, 0, UINT8_MAX, '.');\n-\tGET_CB_FIELD(in, d, 0, UINT8_MAX, '/');\n-\tGET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);\n-\n-\taddr[0] = IPv4(a, b, c, d);\n-\tmask_len[0] = m;\n-\n-\treturn 0;\n-}\n-\n-static int\n-parse_cb_ipv4vlan_rule(char *str, struct rte_acl_rule *v, int has_userdata)\n-{\n-\tint i, rc;\n-\tchar *s, *sp, *in[CB_FLD_NUM];\n-\tstatic const char *dlm = \" \\t\\n\";\n-\tint dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA;\n-\ts = str;\n-\n-\tfor (i = 0; i != dim; i++, s = NULL) {\n-\t\tin[i] = strtok_r(s, dlm, &sp);\n-\t\tif (in[i] == NULL)\n-\t\t\treturn -EINVAL;\n-\t}\n-\n-\trc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],\n-\t\t\t&v->field[SRC_FIELD_IPV4].value.u32,\n-\t\t\t&v->field[SRC_FIELD_IPV4].mask_range.u32);\n-\tif (rc != 0) {\n-\t\t\tacl_log(\"failed to read source address/mask: %s\\n\",\n-\t\t\tin[CB_FLD_SRC_ADDR]);\n-\t\treturn rc;\n-\t}\n-\n-\trc = parse_ipv4_net(in[CB_FLD_DST_ADDR],\n-\t\t\t&v->field[DST_FIELD_IPV4].value.u32,\n-\t\t\t&v->field[DST_FIELD_IPV4].mask_range.u32);\n-\tif (rc != 0) {\n-\t\tacl_log(\"failed to read destination address/mask: %s\\n\",\n-\t\t\tin[CB_FLD_DST_ADDR]);\n-\t\treturn rc;\n-\t}\n-\n-\tGET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],\n-\t\tv->field[SRCP_FIELD_IPV4].value.u16,\n-\t\t0, UINT16_MAX, 0);\n-\tGET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],\n-\t\tv->field[SRCP_FIELD_IPV4].mask_range.u16,\n-\t\t0, UINT16_MAX, 0);\n-\n-\tif (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,\n-\t\t\tsizeof(cb_port_delim)) != 0)\n-\t\treturn -EINVAL;\n-\n-\tGET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],\n-\t\tv->field[DSTP_FIELD_IPV4].value.u16,\n-\t\t0, UINT16_MAX, 0);\n-\tGET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],\n-\t\tv->field[DSTP_FIELD_IPV4].mask_range.u16,\n-\t\t0, UINT16_MAX, 0);\n-\n-\tif (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,\n-\t\t\tsizeof(cb_port_delim)) != 0)\n-\t\treturn -EINVAL;\n-\n-\tif (v->field[SRCP_FIELD_IPV4].mask_range.u16\n-\t\t\t< v->field[SRCP_FIELD_IPV4].value.u16\n-\t\t\t|| v->field[DSTP_FIELD_IPV4].mask_range.u16\n-\t\t\t< v->field[DSTP_FIELD_IPV4].value.u16)\n-\t\treturn -EINVAL;\n-\n-\tGET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8,\n-\t\t0, UINT8_MAX, '/');\n-\tGET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8,\n-\t\t0, UINT8_MAX, 0);\n-\n-\tif (has_userdata)\n-\t\tGET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 0,\n-\t\t\tUINT32_MAX, 0);\n-\n-\treturn 0;\n-}\n-\n-static int\n-add_rules(const char *rule_path,\n-\t\tstruct rte_acl_rule **proute_base,\n-\t\tunsigned int *proute_num,\n-\t\tstruct rte_acl_rule **pacl_base,\n-\t\tunsigned int *pacl_num, uint32_t rule_size,\n-\t\tint (*parser)(char *, struct rte_acl_rule*, int))\n-{\n-\tuint8_t *acl_rules, *route_rules;\n-\tstruct rte_acl_rule *next;\n-\tunsigned int acl_num = 0, route_num = 0, total_num = 0;\n-\tunsigned int acl_cnt = 0, route_cnt = 0;\n-\tchar buff[LINE_MAX];\n-\tFILE *fh = fopen(rule_path, \"rb\");\n-\tunsigned int i = 0;\n-\n-\tif (fh == NULL)\n-\t\trte_exit(EXIT_FAILURE, \"%s: Open %s failed\\n\", __func__,\n-\t\t\trule_path);\n-\n-\twhile ((fgets(buff, LINE_MAX, fh) != NULL)) {\n-\t\tif (buff[0] == ROUTE_LEAD_CHAR)\n-\t\t\troute_num++;\n-\t\telse if (buff[0] == ACL_LEAD_CHAR)\n-\t\t\tacl_num++;\n-\t}\n-\n-\tif (0 == route_num)\n-\t\trte_exit(EXIT_FAILURE, \"Not find any route entries in %s!\\n\",\n-\t\t\t\trule_path);\n-\n-\tfseek(fh, 0, SEEK_SET);\n-\n-\tacl_rules = calloc(acl_num, rule_size);\n-\n-\tif (NULL == acl_rules)\n-\t\trte_exit(EXIT_FAILURE, \"%s: failed to malloc memory\\n\",\n-\t\t\t__func__);\n-\n-\troute_rules = calloc(route_num, rule_size);\n-\n-\tif (NULL == route_rules)\n-\t\trte_exit(EXIT_FAILURE, \"%s: failed to malloc memory\\n\",\n-\t\t\t__func__);\n-\n-\ti = 0;\n-\twhile (fgets(buff, LINE_MAX, fh) != NULL) {\n-\t\ti++;\n-\n-\t\tif (is_bypass_line(buff))\n-\t\t\tcontinue;\n-\n-\t\tchar s = buff[0];\n-\n-\t\t/* Route entry */\n-\t\tif (s == ROUTE_LEAD_CHAR)\n-\t\t\tnext = (struct rte_acl_rule *)(route_rules +\n-\t\t\t\troute_cnt * rule_size);\n-\n-\t\t/* ACL entry */\n-\t\telse if (s == ACL_LEAD_CHAR)\n-\t\t\tnext = (struct rte_acl_rule *)(acl_rules +\n-\t\t\t\tacl_cnt * rule_size);\n-\n-\t\t/* Illegal line */\n-\t\telse\n-\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\"%s Line %u: should start with leading \"\n-\t\t\t\t\"char %c or %c\\n\",\n-\t\t\t\trule_path, i, ROUTE_LEAD_CHAR, ACL_LEAD_CHAR);\n-\n-\t\tif (parser(buff + 1, next, s == ROUTE_LEAD_CHAR) != 0)\n-\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\"%s Line %u: parse rules error\\n\",\n-\t\t\t\trule_path, i);\n-\n-\t\tif (s == ROUTE_LEAD_CHAR) {\n-\t\t\t/* Check the forwarding port number */\n-\t\t\tif ((enabled_port_mask & (1 << next->data.userdata)) ==\n-\t\t\t\t\t0)\n-\t\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\t\"%s Line %u: fwd number illegal:%u\\n\",\n-\t\t\t\t\trule_path, i, next->data.userdata);\n-\t\t\tnext->data.userdata += FWD_PORT_SHIFT;\n-\t\t\troute_cnt++;\n-\t\t} else {\n-\t\t\tnext->data.userdata = ACL_DENY_SIGNATURE + acl_cnt;\n-\t\t\tacl_cnt++;\n-\t\t}\n-\n-\t\tnext->data.priority = RTE_ACL_MAX_PRIORITY - total_num;\n-\t\tnext->data.category_mask = -1;\n-\t\ttotal_num++;\n-\t}\n-\n-\tfclose(fh);\n-\n-\t*pacl_base = (struct rte_acl_rule *)acl_rules;\n-\t*pacl_num = acl_num;\n-\t*proute_base = (struct rte_acl_rule *)route_rules;\n-\t*proute_num = route_cnt;\n-\n-\treturn 0;\n-}\n-\n-static void\n-dump_acl_config(void)\n-{\n-\tprintf(\"ACL option are:\\n\");\n-\tprintf(OPTION_RULE_IPV4\": %s\\n\", parm_config.rule_ipv4_name);\n-\tprintf(OPTION_RULE_IPV6\": %s\\n\", parm_config.rule_ipv6_name);\n-\tprintf(OPTION_SCALAR\": %d\\n\", parm_config.scalar);\n-}\n-\n-static int\n-check_acl_config(void)\n-{\n-\tif (parm_config.rule_ipv4_name == NULL) {\n-\t\tacl_log(\"ACL IPv4 rule file not specified\\n\");\n-\t\treturn -1;\n-\t} else if (parm_config.rule_ipv6_name == NULL) {\n-\t\tacl_log(\"ACL IPv6 rule file not specified\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static struct rte_acl_ctx*\n-setup_acl(struct rte_acl_rule *route_base,\n-\t\tstruct rte_acl_rule *acl_base, unsigned int route_num,\n-\t\tunsigned int acl_num, int ipv6, int socketid)\n-{\n-\tchar name[PATH_MAX];\n-\tstruct rte_acl_param acl_param;\n-\tstruct rte_acl_config acl_build_param;\n-\tstruct rte_acl_ctx *context;\n-\tint dim = ipv6 ? RTE_DIM(ipv6_defs) : RTE_DIM(ipv4_defs);\n-\n-\t/* Create ACL contexts */\n-\tsnprintf(name, sizeof(name), \"%s%d\",\n-\t\t\tipv6 ? L3FWD_ACL_IPV6_NAME : L3FWD_ACL_IPV4_NAME,\n-\t\t\tsocketid);\n-\n-\tacl_param.name = name;\n-\tacl_param.socket_id = socketid;\n-\tacl_param.rule_size = RTE_ACL_RULE_SZ(dim);\n-\tacl_param.max_rule_num = MAX_ACL_RULE_NUM;\n-\n-\tif ((context = rte_acl_create(&acl_param)) == NULL)\n-\t\trte_exit(EXIT_FAILURE, \"Failed to create ACL context\\n\");\n-\n-\tif (parm_config.scalar && rte_acl_set_ctx_classify(context,\n-\t\t\tRTE_ACL_CLASSIFY_SCALAR) != 0)\n-\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\"Failed to setup classify method for  ACL context\\n\");\n-\n-\tif (rte_acl_add_rules(context, route_base, route_num) < 0)\n-\t\t\trte_exit(EXIT_FAILURE, \"add rules failed\\n\");\n-\n-\tif (rte_acl_add_rules(context, acl_base, acl_num) < 0)\n-\t\t\trte_exit(EXIT_FAILURE, \"add rules failed\\n\");\n-\n-\t/* Perform builds */\n-\tmemset(&acl_build_param, 0, sizeof(acl_build_param));\n-\n-\tacl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;\n-\tacl_build_param.num_fields = dim;\n-\tmemcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs,\n-\t\tipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs));\n-\n-\tif (rte_acl_build(context, &acl_build_param) != 0)\n-\t\trte_exit(EXIT_FAILURE, \"Failed to build ACL trie\\n\");\n-\n-\trte_acl_dump(context);\n-\n-\treturn context;\n-}\n-\n-static int\n-app_acl_init(void)\n-{\n-\tunsigned lcore_id;\n-\tunsigned int i;\n-\tint socketid;\n-\tstruct rte_acl_rule *acl_base_ipv4, *route_base_ipv4,\n-\t\t*acl_base_ipv6, *route_base_ipv6;\n-\tunsigned int acl_num_ipv4 = 0, route_num_ipv4 = 0,\n-\t\tacl_num_ipv6 = 0, route_num_ipv6 = 0;\n-\n-\tif (check_acl_config() != 0)\n-\t\trte_exit(EXIT_FAILURE, \"Failed to get valid ACL options\\n\");\n-\n-\tdump_acl_config();\n-\n-\t/* Load  rules from the input file */\n-\tif (add_rules(parm_config.rule_ipv4_name, &route_base_ipv4,\n-\t\t\t&route_num_ipv4, &acl_base_ipv4, &acl_num_ipv4,\n-\t\t\tsizeof(struct acl4_rule), &parse_cb_ipv4vlan_rule) < 0)\n-\t\trte_exit(EXIT_FAILURE, \"Failed to add rules\\n\");\n-\n-\tacl_log(\"IPv4 Route entries %u:\\n\", route_num_ipv4);\n-\tdump_ipv4_rules((struct acl4_rule *)route_base_ipv4, route_num_ipv4, 1);\n-\n-\tacl_log(\"IPv4 ACL entries %u:\\n\", acl_num_ipv4);\n-\tdump_ipv4_rules((struct acl4_rule *)acl_base_ipv4, acl_num_ipv4, 1);\n-\n-\tif (add_rules(parm_config.rule_ipv6_name, &route_base_ipv6,\n-\t\t\t&route_num_ipv6,\n-\t\t\t&acl_base_ipv6, &acl_num_ipv6,\n-\t\t\tsizeof(struct acl6_rule), &parse_cb_ipv6_rule) < 0)\n-\t\trte_exit(EXIT_FAILURE, \"Failed to add rules\\n\");\n-\n-\tacl_log(\"IPv6 Route entries %u:\\n\", route_num_ipv6);\n-\tdump_ipv6_rules((struct acl6_rule *)route_base_ipv6, route_num_ipv6, 1);\n-\n-\tacl_log(\"IPv6 ACL entries %u:\\n\", acl_num_ipv6);\n-\tdump_ipv6_rules((struct acl6_rule *)acl_base_ipv6, acl_num_ipv6, 1);\n-\n-\tmemset(&acl_config, 0, sizeof(acl_config));\n-\n-\t/* Check sockets a context should be created on */\n-\tif (!numa_on)\n-\t\tacl_config.mapped[0] = 1;\n-\telse {\n-\t\tfor (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n-\t\t\tif (rte_lcore_is_enabled(lcore_id) == 0)\n-\t\t\t\tcontinue;\n-\n-\t\t\tsocketid = rte_lcore_to_socket_id(lcore_id);\n-\t\t\tif (socketid >= NB_SOCKETS) {\n-\t\t\t\tacl_log(\"Socket %d of lcore %u is out \"\n-\t\t\t\t\t\"of range %d\\n\",\n-\t\t\t\t\tsocketid, lcore_id, NB_SOCKETS);\n-\t\t\t\tfree(route_base_ipv4);\n-\t\t\t\tfree(route_base_ipv6);\n-\t\t\t\tfree(acl_base_ipv4);\n-\t\t\t\tfree(acl_base_ipv6);\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\n-\t\t\tacl_config.mapped[socketid] = 1;\n-\t\t}\n-\t}\n-\n-\tfor (i = 0; i < NB_SOCKETS; i++) {\n-\t\tif (acl_config.mapped[i]) {\n-\t\t\tacl_config.acx_ipv4[i] = setup_acl(route_base_ipv4,\n-\t\t\t\tacl_base_ipv4, route_num_ipv4, acl_num_ipv4,\n-\t\t\t\t0, i);\n-\n-\t\t\tacl_config.acx_ipv6[i] = setup_acl(route_base_ipv6,\n-\t\t\t\tacl_base_ipv6, route_num_ipv6, acl_num_ipv6,\n-\t\t\t\t1, i);\n-\t\t}\n-\t}\n-\n-\tfree(route_base_ipv4);\n-\tfree(route_base_ipv6);\n-\n-#ifdef L3FWDACL_DEBUG\n-\tacl_config.rule_ipv4 = (struct acl4_rule *)acl_base_ipv4;\n-\tacl_config.rule_ipv6 = (struct acl6_rule *)acl_base_ipv6;\n-#else\n-\tfree(acl_base_ipv4);\n-\tfree(acl_base_ipv6);\n-#endif\n-\n-\treturn 0;\n-}\n-\n-/***********************end of ACL part******************************/\n-\n-struct lcore_conf {\n-\tuint16_t n_rx_queue;\n-\tstruct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];\n-\tuint16_t n_tx_port;\n-\tuint16_t tx_port_id[RTE_MAX_ETHPORTS];\n-\tuint16_t tx_queue_id[RTE_MAX_ETHPORTS];\n-\tstruct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];\n-} __rte_cache_aligned;\n-\n-static struct lcore_conf lcore_conf[RTE_MAX_LCORE];\n-\n-/* Enqueue a single packet, and send burst if queue is filled */\n-static inline void\n-send_single_packet(struct rte_mbuf *m, uint8_t port)\n-{\n-\tuint32_t lcore_id;\n-\tstruct lcore_conf *qconf;\n-\n-\tlcore_id = rte_lcore_id();\n-\n-\tqconf = &lcore_conf[lcore_id];\n-\trte_eth_tx_buffer(port, qconf->tx_queue_id[port],\n-\t\t\tqconf->tx_buffer[port], m);\n-}\n-\n-#ifdef DO_RFC_1812_CHECKS\n-static inline int\n-is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len)\n-{\n-\t/* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */\n-\t/*\n-\t * 1. The packet length reported by the Link Layer must be large\n-\t * enough to hold the minimum length legal IP datagram (20 bytes).\n-\t */\n-\tif (link_len < sizeof(struct ipv4_hdr))\n-\t\treturn -1;\n-\n-\t/* 2. The IP checksum must be correct. */\n-\t/* this is checked in H/W */\n-\n-\t/*\n-\t * 3. The IP version number must be 4. If the version number is not 4\n-\t * then the packet may be another version of IP, such as IPng or\n-\t * ST-II.\n-\t */\n-\tif (((pkt->version_ihl) >> 4) != 4)\n-\t\treturn -3;\n-\t/*\n-\t * 4. The IP header length field must be large enough to hold the\n-\t * minimum length legal IP datagram (20 bytes = 5 words).\n-\t */\n-\tif ((pkt->version_ihl & 0xf) < 5)\n-\t\treturn -4;\n-\n-\t/*\n-\t * 5. The IP total length field must be large enough to hold the IP\n-\t * datagram header, whose length is specified in the IP header length\n-\t * field.\n-\t */\n-\tif (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct ipv4_hdr))\n-\t\treturn -5;\n-\n-\treturn 0;\n-}\n-#endif\n-\n-/* main processing loop */\n-static int\n-main_loop(__attribute__((unused)) void *dummy)\n-{\n-\tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n-\tunsigned lcore_id;\n-\tuint64_t prev_tsc, diff_tsc, cur_tsc;\n-\tint i, nb_rx;\n-\tuint8_t portid, queueid;\n-\tstruct lcore_conf *qconf;\n-\tint socketid;\n-\tconst uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)\n-\t\t\t/ US_PER_S * BURST_TX_DRAIN_US;\n-\n-\tprev_tsc = 0;\n-\tlcore_id = rte_lcore_id();\n-\tqconf = &lcore_conf[lcore_id];\n-\tsocketid = rte_lcore_to_socket_id(lcore_id);\n-\n-\tif (qconf->n_rx_queue == 0) {\n-\t\tRTE_LOG(INFO, L3FWD, \"lcore %u has nothing to do\\n\", lcore_id);\n-\t\treturn 0;\n-\t}\n-\n-\tRTE_LOG(INFO, L3FWD, \"entering main loop on lcore %u\\n\", lcore_id);\n-\n-\tfor (i = 0; i < qconf->n_rx_queue; i++) {\n-\n-\t\tportid = qconf->rx_queue_list[i].port_id;\n-\t\tqueueid = qconf->rx_queue_list[i].queue_id;\n-\t\tRTE_LOG(INFO, L3FWD,\n-\t\t\t\" -- lcoreid=%u portid=%hhu rxqueueid=%hhu\\n\",\n-\t\t\tlcore_id, portid, queueid);\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-\t\t\tfor (i = 0; i < qconf->n_tx_port; ++i) {\n-\t\t\t\tportid = qconf->tx_port_id[i];\n-\t\t\t\trte_eth_tx_buffer_flush(portid,\n-\t\t\t\t\t\tqconf->tx_queue_id[portid],\n-\t\t\t\t\t\tqconf->tx_buffer[portid]);\n-\t\t\t}\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->n_rx_queue; ++i) {\n-\n-\t\t\tportid = qconf->rx_queue_list[i].port_id;\n-\t\t\tqueueid = qconf->rx_queue_list[i].queue_id;\n-\t\t\tnb_rx = rte_eth_rx_burst(portid, queueid,\n-\t\t\t\tpkts_burst, MAX_PKT_BURST);\n-\n-\t\t\tif (nb_rx > 0) {\n-\t\t\t\tstruct acl_search_t acl_search;\n-\n-\t\t\t\tprepare_acl_parameter(pkts_burst, &acl_search,\n-\t\t\t\t\tnb_rx);\n-\n-\t\t\t\tif (acl_search.num_ipv4) {\n-\t\t\t\t\trte_acl_classify(\n-\t\t\t\t\t\tacl_config.acx_ipv4[socketid],\n-\t\t\t\t\t\tacl_search.data_ipv4,\n-\t\t\t\t\t\tacl_search.res_ipv4,\n-\t\t\t\t\t\tacl_search.num_ipv4,\n-\t\t\t\t\t\tDEFAULT_MAX_CATEGORIES);\n-\n-\t\t\t\t\tsend_packets(acl_search.m_ipv4,\n-\t\t\t\t\t\tacl_search.res_ipv4,\n-\t\t\t\t\t\tacl_search.num_ipv4);\n-\t\t\t\t}\n-\n-\t\t\t\tif (acl_search.num_ipv6) {\n-\t\t\t\t\trte_acl_classify(\n-\t\t\t\t\t\tacl_config.acx_ipv6[socketid],\n-\t\t\t\t\t\tacl_search.data_ipv6,\n-\t\t\t\t\t\tacl_search.res_ipv6,\n-\t\t\t\t\t\tacl_search.num_ipv6,\n-\t\t\t\t\t\tDEFAULT_MAX_CATEGORIES);\n-\n-\t\t\t\t\tsend_packets(acl_search.m_ipv6,\n-\t\t\t\t\t\tacl_search.res_ipv6,\n-\t\t\t\t\t\tacl_search.num_ipv6);\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\t}\n-}\n-\n-static int\n-check_lcore_params(void)\n-{\n-\tuint8_t queue, lcore;\n-\tuint16_t i;\n-\tint socketid;\n-\n-\tfor (i = 0; i < nb_lcore_params; ++i) {\n-\t\tqueue = lcore_params[i].queue_id;\n-\t\tif (queue >= MAX_RX_QUEUE_PER_PORT) {\n-\t\t\tprintf(\"invalid queue number: %hhu\\n\", queue);\n-\t\t\treturn -1;\n-\t\t}\n-\t\tlcore = lcore_params[i].lcore_id;\n-\t\tif (!rte_lcore_is_enabled(lcore)) {\n-\t\t\tprintf(\"error: lcore %hhu is not enabled in \"\n-\t\t\t\t\"lcore mask\\n\", lcore);\n-\t\t\treturn -1;\n-\t\t}\n-\t\tsocketid = rte_lcore_to_socket_id(lcore);\n-\t\tif (socketid != 0 && numa_on == 0) {\n-\t\t\tprintf(\"warning: lcore %hhu is on socket %d \"\n-\t\t\t\t\"with numa off\\n\",\n-\t\t\t\tlcore, socketid);\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n-static int\n-check_port_config(const unsigned nb_ports)\n-{\n-\tunsigned portid;\n-\tuint16_t i;\n-\n-\tfor (i = 0; i < nb_lcore_params; ++i) {\n-\t\tportid = lcore_params[i].port_id;\n-\n-\t\tif ((enabled_port_mask & (1 << portid)) == 0) {\n-\t\t\tprintf(\"port %u is not enabled in port mask\\n\", portid);\n-\t\t\treturn -1;\n-\t\t}\n-\t\tif (portid >= nb_ports) {\n-\t\t\tprintf(\"port %u is not present on the board\\n\", portid);\n-\t\t\treturn -1;\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n-static uint8_t\n-get_port_n_rx_queues(const uint8_t port)\n-{\n-\tint queue = -1;\n-\tuint16_t i;\n-\n-\tfor (i = 0; i < nb_lcore_params; ++i) {\n-\t\tif (lcore_params[i].port_id == port &&\n-\t\t\t\tlcore_params[i].queue_id > queue)\n-\t\t\tqueue = lcore_params[i].queue_id;\n-\t}\n-\treturn (uint8_t)(++queue);\n-}\n-\n-static int\n-init_lcore_rx_queues(void)\n-{\n-\tuint16_t i, nb_rx_queue;\n-\tuint8_t lcore;\n-\n-\tfor (i = 0; i < nb_lcore_params; ++i) {\n-\t\tlcore = lcore_params[i].lcore_id;\n-\t\tnb_rx_queue = lcore_conf[lcore].n_rx_queue;\n-\t\tif (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) {\n-\t\t\tprintf(\"error: too many queues (%u) for lcore: %u\\n\",\n-\t\t\t\t(unsigned)nb_rx_queue + 1, (unsigned)lcore);\n-\t\t\treturn -1;\n-\t\t} else {\n-\t\t\tlcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id =\n-\t\t\t\tlcore_params[i].port_id;\n-\t\t\tlcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id =\n-\t\t\t\tlcore_params[i].queue_id;\n-\t\t\tlcore_conf[lcore].n_rx_queue++;\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n-/* display usage */\n-static void\n-print_usage(const char *prgname)\n-{\n-\tprintf(\"%s [EAL options] -- -p PORTMASK -P\"\n-\t\t\"--\"OPTION_RULE_IPV4\"=FILE\"\n-\t\t\"--\"OPTION_RULE_IPV6\"=FILE\"\n-\t\t\"  [--\"OPTION_CONFIG\" (port,queue,lcore)[,(port,queue,lcore]]\"\n-\t\t\"  [--\"OPTION_ENBJMO\" [--max-pkt-len PKTLEN]]\\n\"\n-\t\t\"  -p PORTMASK: hexadecimal bitmask of ports to configure\\n\"\n-\t\t\"  -P : enable promiscuous mode\\n\"\n-\t\t\"  --\"OPTION_CONFIG\": (port,queue,lcore): \"\n-\t\t\"rx queues configuration\\n\"\n-\t\t\"  --\"OPTION_NONUMA\": optional, disable numa awareness\\n\"\n-\t\t\"  --\"OPTION_ENBJMO\": enable jumbo frame\"\n-\t\t\" which max packet len is PKTLEN in decimal (64-9600)\\n\"\n-\t\t\"  --\"OPTION_RULE_IPV4\"=FILE: specify the ipv4 rules entries \"\n-\t\t\"file. \"\n-\t\t\"Each rule occupy one line. \"\n-\t\t\"2 kinds of rules are supported. \"\n-\t\t\"One is ACL entry at while line leads with character '%c', \"\n-\t\t\"another is route entry at while line leads with \"\n-\t\t\"character '%c'.\\n\"\n-\t\t\"  --\"OPTION_RULE_IPV6\"=FILE: specify the ipv6 rules \"\n-\t\t\"entries file.\\n\"\n-\t\t\"  --\"OPTION_SCALAR\": Use scalar function to do lookup\\n\",\n-\t\tprgname, ACL_LEAD_CHAR, ROUTE_LEAD_CHAR);\n-}\n-\n-static int\n-parse_max_pkt_len(const char *pktlen)\n-{\n-\tchar *end = NULL;\n-\tunsigned long len;\n-\n-\t/* parse decimal string */\n-\tlen = strtoul(pktlen, &end, 10);\n-\tif ((pktlen[0] == '\\0') || (end == NULL) || (*end != '\\0'))\n-\t\treturn -1;\n-\n-\tif (len == 0)\n-\t\treturn -1;\n-\n-\treturn len;\n-}\n-\n-static int\n-parse_portmask(const char *portmask)\n-{\n-\tchar *end = NULL;\n-\tunsigned long pm;\n-\n-\t/* parse hexadecimal string */\n-\tpm = strtoul(portmask, &end, 16);\n-\tif ((portmask[0] == '\\0') || (end == NULL) || (*end != '\\0'))\n-\t\treturn -1;\n-\n-\tif (pm == 0)\n-\t\treturn -1;\n-\n-\treturn pm;\n-}\n-\n-static int\n-parse_config(const char *q_arg)\n-{\n-\tchar s[256];\n-\tconst char *p, *p0 = q_arg;\n-\tchar *end;\n-\tenum fieldnames {\n-\t\tFLD_PORT = 0,\n-\t\tFLD_QUEUE,\n-\t\tFLD_LCORE,\n-\t\t_NUM_FLD\n-\t};\n-\tunsigned long int_fld[_NUM_FLD];\n-\tchar *str_fld[_NUM_FLD];\n-\tint i;\n-\tunsigned size;\n-\n-\tnb_lcore_params = 0;\n-\n-\twhile ((p = strchr(p0, '(')) != NULL) {\n-\t\t++p;\n-\t\tif ((p0 = strchr(p, ')')) == NULL)\n-\t\t\treturn -1;\n-\n-\t\tsize = p0 - p;\n-\t\tif (size >= sizeof(s))\n-\t\t\treturn -1;\n-\n-\t\tsnprintf(s, sizeof(s), \"%.*s\", size, p);\n-\t\tif (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') !=\n-\t\t\t\t_NUM_FLD)\n-\t\t\treturn -1;\n-\t\tfor (i = 0; i < _NUM_FLD; i++) {\n-\t\t\terrno = 0;\n-\t\t\tint_fld[i] = strtoul(str_fld[i], &end, 0);\n-\t\t\tif (errno != 0 || end == str_fld[i] || int_fld[i] > 255)\n-\t\t\t\treturn -1;\n-\t\t}\n-\t\tif (nb_lcore_params >= MAX_LCORE_PARAMS) {\n-\t\t\tprintf(\"exceeded max number of lcore params: %hu\\n\",\n-\t\t\t\tnb_lcore_params);\n-\t\t\treturn -1;\n-\t\t}\n-\t\tlcore_params_array[nb_lcore_params].port_id =\n-\t\t\t(uint8_t)int_fld[FLD_PORT];\n-\t\tlcore_params_array[nb_lcore_params].queue_id =\n-\t\t\t(uint8_t)int_fld[FLD_QUEUE];\n-\t\tlcore_params_array[nb_lcore_params].lcore_id =\n-\t\t\t(uint8_t)int_fld[FLD_LCORE];\n-\t\t++nb_lcore_params;\n-\t}\n-\tlcore_params = lcore_params_array;\n-\treturn 0;\n-}\n-\n-/* Parse the argument given in the command line of the application */\n-static int\n-parse_args(int argc, char **argv)\n-{\n-\tint opt, ret;\n-\tchar **argvopt;\n-\tint option_index;\n-\tchar *prgname = argv[0];\n-\tstatic struct option lgopts[] = {\n-\t\t{OPTION_CONFIG, 1, 0, 0},\n-\t\t{OPTION_NONUMA, 0, 0, 0},\n-\t\t{OPTION_ENBJMO, 0, 0, 0},\n-\t\t{OPTION_RULE_IPV4, 1, 0, 0},\n-\t\t{OPTION_RULE_IPV6, 1, 0, 0},\n-\t\t{OPTION_SCALAR, 0, 0, 0},\n-\t\t{NULL, 0, 0, 0}\n-\t};\n-\n-\targvopt = argv;\n-\n-\twhile ((opt = getopt_long(argc, argvopt, \"p:P\",\n-\t\t\t\tlgopts, &option_index)) != EOF) {\n-\n-\t\tswitch (opt) {\n-\t\t/* portmask */\n-\t\tcase 'p':\n-\t\t\tenabled_port_mask = parse_portmask(optarg);\n-\t\t\tif (enabled_port_mask == 0) {\n-\t\t\t\tprintf(\"invalid portmask\\n\");\n-\t\t\t\tprint_usage(prgname);\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase 'P':\n-\t\t\tprintf(\"Promiscuous mode selected\\n\");\n-\t\t\tpromiscuous_on = 1;\n-\t\t\tbreak;\n-\n-\t\t/* long options */\n-\t\tcase 0:\n-\t\t\tif (!strncmp(lgopts[option_index].name,\n-\t\t\t\t\tOPTION_CONFIG,\n-\t\t\t\t\tsizeof(OPTION_CONFIG))) {\n-\t\t\t\tret = parse_config(optarg);\n-\t\t\t\tif (ret) {\n-\t\t\t\t\tprintf(\"invalid config\\n\");\n-\t\t\t\t\tprint_usage(prgname);\n-\t\t\t\t\treturn -1;\n-\t\t\t\t}\n-\t\t\t}\n-\n-\t\t\tif (!strncmp(lgopts[option_index].name,\n-\t\t\t\t\tOPTION_NONUMA,\n-\t\t\t\t\tsizeof(OPTION_NONUMA))) {\n-\t\t\t\tprintf(\"numa is disabled\\n\");\n-\t\t\t\tnuma_on = 0;\n-\t\t\t}\n-\n-\t\t\tif (!strncmp(lgopts[option_index].name,\n-\t\t\t\t\tOPTION_ENBJMO, sizeof(OPTION_ENBJMO))) {\n-\t\t\t\tstruct option lenopts = {\n-\t\t\t\t\t\"max-pkt-len\",\n-\t\t\t\t\trequired_argument,\n-\t\t\t\t\t0,\n-\t\t\t\t\t0\n-\t\t\t\t};\n-\n-\t\t\t\tprintf(\"jumbo frame is enabled\\n\");\n-\t\t\t\tport_conf.rxmode.jumbo_frame = 1;\n-\n-\t\t\t\t/*\n-\t\t\t\t * if no max-pkt-len set, then use the\n-\t\t\t\t * default value ETHER_MAX_LEN\n-\t\t\t\t */\n-\t\t\t\tif (0 == getopt_long(argc, argvopt, \"\",\n-\t\t\t\t\t\t&lenopts, &option_index)) {\n-\t\t\t\t\tret = parse_max_pkt_len(optarg);\n-\t\t\t\t\tif ((ret < 64) ||\n-\t\t\t\t\t\t(ret > MAX_JUMBO_PKT_LEN)) {\n-\t\t\t\t\t\tprintf(\"invalid packet \"\n-\t\t\t\t\t\t\t\"length\\n\");\n-\t\t\t\t\t\tprint_usage(prgname);\n-\t\t\t\t\t\treturn -1;\n-\t\t\t\t\t}\n-\t\t\t\t\tport_conf.rxmode.max_rx_pkt_len = ret;\n-\t\t\t\t}\n-\t\t\t\tprintf(\"set jumbo frame max packet length \"\n-\t\t\t\t\t\"to %u\\n\",\n-\t\t\t\t\t(unsigned int)\n-\t\t\t\t\tport_conf.rxmode.max_rx_pkt_len);\n-\t\t\t}\n-\n-\t\t\tif (!strncmp(lgopts[option_index].name,\n-\t\t\t\t\tOPTION_RULE_IPV4,\n-\t\t\t\t\tsizeof(OPTION_RULE_IPV4)))\n-\t\t\t\tparm_config.rule_ipv4_name = optarg;\n-\n-\t\t\tif (!strncmp(lgopts[option_index].name,\n-\t\t\t\t\tOPTION_RULE_IPV6,\n-\t\t\t\t\tsizeof(OPTION_RULE_IPV6))) {\n-\t\t\t\tparm_config.rule_ipv6_name = optarg;\n-\t\t\t}\n-\n-\t\t\tif (!strncmp(lgopts[option_index].name,\n-\t\t\t\t\tOPTION_SCALAR, sizeof(OPTION_SCALAR)))\n-\t\t\t\tparm_config.scalar = 1;\n-\n-\n-\t\t\tbreak;\n-\n-\t\tdefault:\n-\t\t\tprint_usage(prgname);\n-\t\t\treturn -1;\n-\t\t}\n-\t}\n-\n-\tif (optind >= 0)\n-\t\targv[optind-1] = prgname;\n-\n-\tret = optind-1;\n-\toptind = 0; /* reset getopt lib */\n-\treturn ret;\n-}\n-\n-static void\n-print_ethaddr(const char *name, const struct ether_addr *eth_addr)\n-{\n-\tchar buf[ETHER_ADDR_FMT_SIZE];\n-\tether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr);\n-\tprintf(\"%s%s\", name, buf);\n-}\n-\n-static int\n-init_mem(unsigned nb_mbuf)\n-{\n-\tint socketid;\n-\tunsigned lcore_id;\n-\tchar s[64];\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-\n-\t\tif (numa_on)\n-\t\t\tsocketid = rte_lcore_to_socket_id(lcore_id);\n-\t\telse\n-\t\t\tsocketid = 0;\n-\n-\t\tif (socketid >= NB_SOCKETS) {\n-\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\"Socket %d of lcore %u is out of range %d\\n\",\n-\t\t\t\tsocketid, lcore_id, NB_SOCKETS);\n-\t\t}\n-\t\tif (pktmbuf_pool[socketid] == NULL) {\n-\t\t\tsnprintf(s, sizeof(s), \"mbuf_pool_%d\", socketid);\n-\t\t\tpktmbuf_pool[socketid] =\n-\t\t\t\trte_pktmbuf_pool_create(s, nb_mbuf,\n-\t\t\t\t\tMEMPOOL_CACHE_SIZE, 0,\n-\t\t\t\t\tRTE_MBUF_DEFAULT_BUF_SIZE,\n-\t\t\t\t\tsocketid);\n-\t\t\tif (pktmbuf_pool[socketid] == NULL)\n-\t\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\t\"Cannot init mbuf pool on socket %d\\n\",\n-\t\t\t\t\tsocketid);\n-\t\t\telse\n-\t\t\t\tprintf(\"Allocated mbuf pool on socket %d\\n\",\n-\t\t\t\t\tsocketid);\n-\t\t}\n-\t}\n-\treturn 0;\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 == ETH_LINK_DOWN) {\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-int\n-main(int argc, char **argv)\n-{\n-\tstruct lcore_conf *qconf;\n-\tstruct rte_eth_dev_info dev_info;\n-\tstruct rte_eth_txconf *txconf;\n-\tint ret;\n-\tunsigned nb_ports;\n-\tuint16_t queueid;\n-\tunsigned lcore_id;\n-\tuint32_t n_tx_queue, nb_lcores;\n-\tuint8_t portid, nb_rx_queue, queue, socketid;\n-\n-\t/* init EAL */\n-\tret = rte_eal_init(argc, argv);\n-\tif (ret < 0)\n-\t\trte_exit(EXIT_FAILURE, \"Invalid EAL parameters\\n\");\n-\targc -= ret;\n-\targv += ret;\n-\n-\t/* parse application arguments (after the EAL ones) */\n-\tret = parse_args(argc, argv);\n-\tif (ret < 0)\n-\t\trte_exit(EXIT_FAILURE, \"Invalid L3FWD parameters\\n\");\n-\n-\tif (check_lcore_params() < 0)\n-\t\trte_exit(EXIT_FAILURE, \"check_lcore_params failed\\n\");\n-\n-\tret = init_lcore_rx_queues();\n-\tif (ret < 0)\n-\t\trte_exit(EXIT_FAILURE, \"init_lcore_rx_queues failed\\n\");\n-\n-\tnb_ports = rte_eth_dev_count();\n-\n-\tif (check_port_config(nb_ports) < 0)\n-\t\trte_exit(EXIT_FAILURE, \"check_port_config failed\\n\");\n-\n-\t/* Add ACL rules and route entries, build trie */\n-\tif (app_acl_init() < 0)\n-\t\trte_exit(EXIT_FAILURE, \"app_acl_init failed\\n\");\n-\n-\tnb_lcores = rte_lcore_count();\n-\n-\t/* initialize all ports */\n-\tfor (portid = 0; portid < nb_ports; portid++) {\n-\t\t/* skip ports that are not enabled */\n-\t\tif ((enabled_port_mask & (1 << portid)) == 0) {\n-\t\t\tprintf(\"\\nSkipping disabled port %d\\n\", portid);\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* init port */\n-\t\tprintf(\"Initializing port %d ... \", portid);\n-\t\tfflush(stdout);\n-\n-\t\tnb_rx_queue = get_port_n_rx_queues(portid);\n-\t\tn_tx_queue = nb_lcores;\n-\t\tif (n_tx_queue > MAX_TX_QUEUE_PER_PORT)\n-\t\t\tn_tx_queue = MAX_TX_QUEUE_PER_PORT;\n-\t\tprintf(\"Creating queues: nb_rxq=%d nb_txq=%u... \",\n-\t\t\tnb_rx_queue, (unsigned)n_tx_queue);\n-\t\tret = rte_eth_dev_configure(portid, nb_rx_queue,\n-\t\t\t\t\t(uint16_t)n_tx_queue, &port_conf);\n-\t\tif (ret < 0)\n-\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\"Cannot configure device: err=%d, port=%d\\n\",\n-\t\t\t\tret, portid);\n-\n-\t\trte_eth_macaddr_get(portid, &ports_eth_addr[portid]);\n-\t\tprint_ethaddr(\" Address:\", &ports_eth_addr[portid]);\n-\t\tprintf(\", \");\n-\n-\t\t/* init memory */\n-\t\tret = init_mem(NB_MBUF);\n-\t\tif (ret < 0)\n-\t\t\trte_exit(EXIT_FAILURE, \"init_mem failed\\n\");\n-\n-\t\tfor (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n-\t\t\tif (rte_lcore_is_enabled(lcore_id) == 0)\n-\t\t\t\tcontinue;\n-\n-\t\t\t/* Initialize TX buffers */\n-\t\t\tqconf = &lcore_conf[lcore_id];\n-\t\t\tqconf->tx_buffer[portid] = rte_zmalloc_socket(\"tx_buffer\",\n-\t\t\t\t\tRTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,\n-\t\t\t\t\trte_eth_dev_socket_id(portid));\n-\t\t\tif (qconf->tx_buffer[portid] == NULL)\n-\t\t\t\trte_exit(EXIT_FAILURE, \"Can't allocate tx buffer for port %u\\n\",\n-\t\t\t\t\t\t(unsigned) portid);\n-\n-\t\t\trte_eth_tx_buffer_init(qconf->tx_buffer[portid], MAX_PKT_BURST);\n-\t\t}\n-\n-\t\t/* init one TX queue per couple (lcore,port) */\n-\t\tqueueid = 0;\n-\t\tfor (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n-\t\t\tif (rte_lcore_is_enabled(lcore_id) == 0)\n-\t\t\t\tcontinue;\n-\n-\t\t\tif (numa_on)\n-\t\t\t\tsocketid = (uint8_t)\n-\t\t\t\t\trte_lcore_to_socket_id(lcore_id);\n-\t\t\telse\n-\t\t\t\tsocketid = 0;\n-\n-\t\t\tprintf(\"txq=%u,%d,%d \", lcore_id, queueid, socketid);\n-\t\t\tfflush(stdout);\n-\n-\t\t\trte_eth_dev_info_get(portid, &dev_info);\n-\t\t\ttxconf = &dev_info.default_txconf;\n-\t\t\tif (port_conf.rxmode.jumbo_frame)\n-\t\t\t\ttxconf->txq_flags = 0;\n-\t\t\tret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,\n-\t\t\t\t\t\t     socketid, txconf);\n-\t\t\tif (ret < 0)\n-\t\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\t\"rte_eth_tx_queue_setup: err=%d, \"\n-\t\t\t\t\t\"port=%d\\n\", ret, portid);\n-\n-\t\t\tqconf = &lcore_conf[lcore_id];\n-\t\t\tqconf->tx_queue_id[portid] = queueid;\n-\t\t\tqueueid++;\n-\n-\t\t\tqconf->tx_port_id[qconf->n_tx_port] = portid;\n-\t\t\tqconf->n_tx_port++;\n-\t\t}\n-\t\tprintf(\"\\n\");\n-\t}\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-\t\tqconf = &lcore_conf[lcore_id];\n-\t\tprintf(\"\\nInitializing rx queues on lcore %u ... \", lcore_id);\n-\t\tfflush(stdout);\n-\t\t/* init RX queues */\n-\t\tfor (queue = 0; queue < qconf->n_rx_queue; ++queue) {\n-\t\t\tportid = qconf->rx_queue_list[queue].port_id;\n-\t\t\tqueueid = qconf->rx_queue_list[queue].queue_id;\n-\n-\t\t\tif (numa_on)\n-\t\t\t\tsocketid = (uint8_t)\n-\t\t\t\t\trte_lcore_to_socket_id(lcore_id);\n-\t\t\telse\n-\t\t\t\tsocketid = 0;\n-\n-\t\t\tprintf(\"rxq=%d,%d,%d \", portid, queueid, socketid);\n-\t\t\tfflush(stdout);\n-\n-\t\t\tret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,\n-\t\t\t\t\tsocketid, NULL,\n-\t\t\t\t\tpktmbuf_pool[socketid]);\n-\t\t\tif (ret < 0)\n-\t\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\t\"rte_eth_rx_queue_setup: err=%d,\"\n-\t\t\t\t\t\"port=%d\\n\", ret, portid);\n-\t\t}\n-\t}\n-\n-\tprintf(\"\\n\");\n-\n-\t/* start ports */\n-\tfor (portid = 0; portid < nb_ports; portid++) {\n-\t\tif ((enabled_port_mask & (1 << portid)) == 0)\n-\t\t\tcontinue;\n-\n-\t\t/* Start device */\n-\t\tret = rte_eth_dev_start(portid);\n-\t\tif (ret < 0)\n-\t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\"rte_eth_dev_start: err=%d, port=%d\\n\",\n-\t\t\t\tret, portid);\n-\n-\t\t/*\n-\t\t * If enabled, put device in promiscuous mode.\n-\t\t * This allows IO forwarding mode to forward packets\n-\t\t * to itself through 2 cross-connected  ports of the\n-\t\t * target machine.\n-\t\t */\n-\t\tif (promiscuous_on)\n-\t\t\trte_eth_promiscuous_enable(portid);\n-\t}\n-\n-\tcheck_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask);\n-\n-\t/* launch per-lcore init on every lcore */\n-\trte_eal_mp_remote_launch(main_loop, NULL, CALL_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-}\ndiff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile\nindex 5ce0ce0..151dbe3 100644\n--- a/examples/l3fwd/Makefile\n+++ b/examples/l3fwd/Makefile\n@@ -42,7 +42,7 @@ include $(RTE_SDK)/mk/rte.vars.mk\n APP = l3fwd\n \n # all source are stored in SRCS-y\n-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c\n+SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_acl.c\n \n CFLAGS += -I$(SRCDIR)\n CFLAGS += -O3 $(USER_FLAGS)\ndiff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h\nindex 011ba14..93e08f6 100644\n--- a/examples/l3fwd/l3fwd.h\n+++ b/examples/l3fwd/l3fwd.h\n@@ -77,6 +77,24 @@\n #endif\n #define HASH_ENTRY_NUMBER_DEFAULT\t4\n \n+/* Config options */\n+#define OPTION_CONFIG           \"config\"\n+#define OPTION_NONUMA           \"no-numa\"\n+#define OPTION_ENBJMO           \"enable-jumbo\"\n+#define OPTION_RULE_IPV4        \"rule_ipv4\"\n+#define OPTION_RULE_IPV6        \"rule_ipv6\"\n+#define OPTION_SCALAR           \"scalar\"\n+#define OPTION_ETH_DEST         \"eth-dest\"\n+#define OPTION_IPV6\t\t\"ipv6\"\n+#define OPTION_HASH_ENTRY_NUM\t\"hash-entry-num\"\n+#define OPTION_PARSE_PTYPE\t\"parse-ptype\"\n+#define OPTION_MAX_PKT_LEN\t\"max-pkt-len\"\n+\n+/*Log file related character defs. */\n+#define ACL_LEAD_CHAR\t\t('@')\n+#define ROUTE_LEAD_CHAR\t\t('R')\n+#define COMMENT_LEAD_CHAR\t('#')\n+\n struct mbuf_table {\n \tuint16_t len;\n \tstruct rte_mbuf *m_table[MAX_PKT_BURST];\n@@ -94,6 +112,7 @@ struct lcore_conf {\n \tuint16_t tx_port_id[RTE_MAX_ETHPORTS];\n \tuint16_t tx_queue_id[RTE_MAX_ETHPORTS];\n \tstruct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];\n+\tstruct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];\n \tvoid *ipv4_lookup_struct;\n \tvoid *ipv6_lookup_struct;\n } __rte_cache_aligned;\n@@ -115,6 +134,8 @@ extern xmm_t val_eth[RTE_MAX_ETHPORTS];\n \n extern struct lcore_conf lcore_conf[RTE_MAX_LCORE];\n \n+extern int numa_on; /**< NUMA is enabled by default. */\n+\n /* Send burst of packets on an output interface */\n static inline int\n send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port)\n@@ -205,12 +226,18 @@ setup_lpm(const int socketid);\n void\n setup_hash(const int socketid);\n \n+void\n+setup_acl(const int socketid);\n+\n int\n em_check_ptype(int portid);\n \n int\n lpm_check_ptype(int portid);\n \n+int\n+acl_check_ptype(int portid);\n+\n uint16_t\n em_cb_parse_ptype(uint8_t port, uint16_t queue, struct rte_mbuf *pkts[],\n \t\t  uint16_t nb_pkts, uint16_t max_pkts, void *user_param);\n@@ -219,12 +246,19 @@ uint16_t\n lpm_cb_parse_ptype(uint8_t port, uint16_t queue, struct rte_mbuf *pkts[],\n \t\t   uint16_t nb_pkts, uint16_t max_pkts, void *user_param);\n \n+uint16_t\n+acl_cb_parse_ptype(uint8_t port, uint16_t queue, struct rte_mbuf *pkts[],\n+\t\t  uint16_t nb_pkts, uint16_t max_pkts, void *user_param);\n+\n int\n em_main_loop(__attribute__((unused)) void *dummy);\n \n int\n lpm_main_loop(__attribute__((unused)) void *dummy);\n \n+int\n+acl_main_loop(__attribute__((unused)) void *dummy);\n+\n /* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */\n void *\n em_get_ipv4_l3fwd_lookup_struct(const int socketid);\n@@ -238,4 +272,19 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);\n void *\n lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);\n \n+void *\n+acl_get_ipv4_l3fwd_lookup_struct(const int socketid);\n+\n+void *\n+acl_get_ipv6_l3fwd_lookup_struct(const int socketid);\n+\n+void\n+l3fwd_acl_set_scalar(void);\n+\n+void\n+l3fwd_acl_set_rule_ipv6_name(const char *optarg);\n+\n+void\n+l3fwd_acl_set_rule_ipv4_name(const char *optarg);\n+\n #endif  /* __L3_FWD_H__ */\ndiff --git a/examples/l3fwd/l3fwd_acl.c b/examples/l3fwd/l3fwd_acl.c\nnew file mode 100644\nindex 0000000..388b978\n--- /dev/null\n+++ b/examples/l3fwd/l3fwd_acl.c\n@@ -0,0 +1,1064 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2016 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+#include <stdio.h>\n+#include <stdlib.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+#include <sys/types.h>\n+#include <string.h>\n+#include <sys/queue.h>\n+#include <stdarg.h>\n+#include <stdbool.h>\n+#include <errno.h>\n+#include <getopt.h>\n+\n+#include <rte_common.h>\n+#include <rte_byteorder.h>\n+#include <rte_log.h>\n+#include <rte_memory.h>\n+#include <rte_memcpy.h>\n+#include <rte_memzone.h>\n+#include <rte_eal.h>\n+#include <rte_per_lcore.h>\n+#include <rte_launch.h>\n+#include <rte_atomic.h>\n+#include <rte_cycles.h>\n+#include <rte_prefetch.h>\n+#include <rte_lcore.h>\n+#include <rte_per_lcore.h>\n+#include <rte_branch_prediction.h>\n+#include <rte_interrupts.h>\n+#include <rte_pci.h>\n+#include <rte_random.h>\n+#include <rte_debug.h>\n+#include <rte_ether.h>\n+#include <rte_ethdev.h>\n+#include <rte_ring.h>\n+#include <rte_mempool.h>\n+#include <rte_mbuf.h>\n+#include <rte_ip.h>\n+#include <rte_tcp.h>\n+#include <rte_udp.h>\n+#include <rte_string_fns.h>\n+#include <rte_acl.h>\n+\n+#include \"l3fwd.h\"\n+\n+/*\n+ * Rule and trace formats definitions.\n+ */\n+\n+enum {\n+\tPROTO_FIELD_IPV4,\n+\tSRC_FIELD_IPV4,\n+\tDST_FIELD_IPV4,\n+\tSRCP_FIELD_IPV4,\n+\tDSTP_FIELD_IPV4,\n+\tNUM_FIELDS_IPV4\n+};\n+\n+/*\n+ * That effectively defines order of IPV4VLAN classifications:\n+ *  - PROTO\n+ *  - VLAN (TAG and DOMAIN)\n+ *  - SRC IP ADDRESS\n+ *  - DST IP ADDRESS\n+ *  - PORTS (SRC and DST)\n+ */\n+enum {\n+\tRTE_ACL_IPV4VLAN_PROTO,\n+\tRTE_ACL_IPV4VLAN_VLAN,\n+\tRTE_ACL_IPV4VLAN_SRC,\n+\tRTE_ACL_IPV4VLAN_DST,\n+\tRTE_ACL_IPV4VLAN_PORTS,\n+\tRTE_ACL_IPV4VLAN_NUM\n+};\n+\n+struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_BITMASK,\n+\t\t.size = sizeof(uint8_t),\n+\t\t.field_index = PROTO_FIELD_IPV4,\n+\t\t.input_index = RTE_ACL_IPV4VLAN_PROTO,\n+\t\t.offset = 0,\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = SRC_FIELD_IPV4,\n+\t\t.input_index = RTE_ACL_IPV4VLAN_SRC,\n+\t\t.offset = offsetof(struct ipv4_hdr, src_addr) -\n+\t\t\toffsetof(struct ipv4_hdr, next_proto_id),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = DST_FIELD_IPV4,\n+\t\t.input_index = RTE_ACL_IPV4VLAN_DST,\n+\t\t.offset = offsetof(struct ipv4_hdr, dst_addr) -\n+\t\t\toffsetof(struct ipv4_hdr, next_proto_id),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_RANGE,\n+\t\t.size = sizeof(uint16_t),\n+\t\t.field_index = SRCP_FIELD_IPV4,\n+\t\t.input_index = RTE_ACL_IPV4VLAN_PORTS,\n+\t\t.offset = sizeof(struct ipv4_hdr) -\n+\t\t\toffsetof(struct ipv4_hdr, next_proto_id),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_RANGE,\n+\t\t.size = sizeof(uint16_t),\n+\t\t.field_index = DSTP_FIELD_IPV4,\n+\t\t.input_index = RTE_ACL_IPV4VLAN_PORTS,\n+\t\t.offset = sizeof(struct ipv4_hdr) -\n+\t\t\toffsetof(struct ipv4_hdr, next_proto_id) +\n+\t\t\tsizeof(uint16_t),\n+\t},\n+};\n+\n+#define\tIPV6_ADDR_LEN\t16\n+#define\tIPV6_ADDR_U16\t(IPV6_ADDR_LEN / sizeof(uint16_t))\n+#define\tIPV6_ADDR_U32\t(IPV6_ADDR_LEN / sizeof(uint32_t))\n+\n+enum {\n+\tPROTO_FIELD_IPV6,\n+\tSRC1_FIELD_IPV6,\n+\tSRC2_FIELD_IPV6,\n+\tSRC3_FIELD_IPV6,\n+\tSRC4_FIELD_IPV6,\n+\tDST1_FIELD_IPV6,\n+\tDST2_FIELD_IPV6,\n+\tDST3_FIELD_IPV6,\n+\tDST4_FIELD_IPV6,\n+\tSRCP_FIELD_IPV6,\n+\tDSTP_FIELD_IPV6,\n+\tNUM_FIELDS_IPV6\n+};\n+\n+struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = {\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_BITMASK,\n+\t\t.size = sizeof(uint8_t),\n+\t\t.field_index = PROTO_FIELD_IPV6,\n+\t\t.input_index = PROTO_FIELD_IPV6,\n+\t\t.offset = 0,\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = SRC1_FIELD_IPV6,\n+\t\t.input_index = SRC1_FIELD_IPV6,\n+\t\t.offset = offsetof(struct ipv6_hdr, src_addr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = SRC2_FIELD_IPV6,\n+\t\t.input_index = SRC2_FIELD_IPV6,\n+\t\t.offset = offsetof(struct ipv6_hdr, src_addr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto) + sizeof(uint32_t),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = SRC3_FIELD_IPV6,\n+\t\t.input_index = SRC3_FIELD_IPV6,\n+\t\t.offset = offsetof(struct ipv6_hdr, src_addr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto) + 2 * sizeof(uint32_t),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = SRC4_FIELD_IPV6,\n+\t\t.input_index = SRC4_FIELD_IPV6,\n+\t\t.offset = offsetof(struct ipv6_hdr, src_addr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto) + 3 * sizeof(uint32_t),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = DST1_FIELD_IPV6,\n+\t\t.input_index = DST1_FIELD_IPV6,\n+\t\t.offset = offsetof(struct ipv6_hdr, dst_addr)\n+\t\t\t\t- offsetof(struct ipv6_hdr, proto),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = DST2_FIELD_IPV6,\n+\t\t.input_index = DST2_FIELD_IPV6,\n+\t\t.offset = offsetof(struct ipv6_hdr, dst_addr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto) + sizeof(uint32_t),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = DST3_FIELD_IPV6,\n+\t\t.input_index = DST3_FIELD_IPV6,\n+\t\t.offset = offsetof(struct ipv6_hdr, dst_addr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto) + 2 * sizeof(uint32_t),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_MASK,\n+\t\t.size = sizeof(uint32_t),\n+\t\t.field_index = DST4_FIELD_IPV6,\n+\t\t.input_index = DST4_FIELD_IPV6,\n+\t\t.offset = offsetof(struct ipv6_hdr, dst_addr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto) + 3 * sizeof(uint32_t),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_RANGE,\n+\t\t.size = sizeof(uint16_t),\n+\t\t.field_index = SRCP_FIELD_IPV6,\n+\t\t.input_index = SRCP_FIELD_IPV6,\n+\t\t.offset = sizeof(struct ipv6_hdr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto),\n+\t},\n+\t{\n+\t\t.type = RTE_ACL_FIELD_TYPE_RANGE,\n+\t\t.size = sizeof(uint16_t),\n+\t\t.field_index = DSTP_FIELD_IPV6,\n+\t\t.input_index = SRCP_FIELD_IPV6,\n+\t\t.offset = sizeof(struct ipv6_hdr) -\n+\t\t\toffsetof(struct ipv6_hdr, proto) + sizeof(uint16_t),\n+\t},\n+};\n+\n+enum {\n+\tCB_FLD_SRC_ADDR,\n+\tCB_FLD_DST_ADDR,\n+\tCB_FLD_SRC_PORT_LOW,\n+\tCB_FLD_SRC_PORT_DLM,\n+\tCB_FLD_SRC_PORT_HIGH,\n+\tCB_FLD_DST_PORT_LOW,\n+\tCB_FLD_DST_PORT_DLM,\n+\tCB_FLD_DST_PORT_HIGH,\n+\tCB_FLD_PROTO,\n+\tCB_FLD_USERDATA,\n+\tCB_FLD_NUM,\n+};\n+\n+RTE_ACL_RULE_DEF(acl4_rule, RTE_DIM(ipv4_defs));\n+RTE_ACL_RULE_DEF(acl6_rule, RTE_DIM(ipv6_defs));\n+\n+struct acl_search_t {\n+\tconst uint8_t *data_ipv4[MAX_PKT_BURST];\n+\tstruct rte_mbuf *m_ipv4[MAX_PKT_BURST];\n+\tuint32_t res_ipv4[MAX_PKT_BURST];\n+\tint num_ipv4;\n+\n+\tconst uint8_t *data_ipv6[MAX_PKT_BURST];\n+\tstruct rte_mbuf *m_ipv6[MAX_PKT_BURST];\n+\tuint32_t res_ipv6[MAX_PKT_BURST];\n+\tint num_ipv6;\n+};\n+\n+static struct {\n+\tchar mapped[NB_SOCKETS];\n+\tstruct rte_acl_ctx *acx_ipv4[NB_SOCKETS];\n+\tstruct rte_acl_ctx *acx_ipv6[NB_SOCKETS];\n+#ifdef L3FWDACL_DEBUG\n+\tstruct acl4_rule *rule_ipv4;\n+\tstruct acl6_rule *rule_ipv6;\n+#endif\n+} acl_config;\n+\n+const char cb_port_delim[] = \":\";\n+\n+static struct {\n+\tconst char *rule_ipv4_name;\n+\tconst char *rule_ipv6_name;\n+\tint scalar;\n+} parm_config;\n+\n+/*\n+ * Print and dump ACL/Route rules functions are defined in\n+ * following header file.\n+ */\n+#include \"l3fwd_acl.h\"\n+\n+/*\n+ * Data path related inline functions are defined in\n+ * following header file.\n+ */\n+#include \"l3fwd_acl_scalar.h\"\n+\n+/*\n+ * API's called during initialization to setup ACL rules.\n+ */\n+void\n+l3fwd_acl_set_rule_ipv4_name(const char *optarg)\n+{\n+\tparm_config.rule_ipv4_name = optarg;\n+}\n+\n+void\n+l3fwd_acl_set_rule_ipv6_name(const char *optarg)\n+{\n+\tparm_config.rule_ipv6_name = optarg;\n+}\n+\n+void\n+l3fwd_acl_set_scalar(void)\n+{\n+\tparm_config.scalar = 1;\n+}\n+\n+/*\n+ * Parses IPV6 address, exepcts the following format:\n+ * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is a hexedecimal digit).\n+ */\n+static int\n+parse_ipv6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32],\n+\tchar dlm)\n+{\n+\tuint32_t addr[IPV6_ADDR_U16];\n+\n+\tGET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':');\n+\tGET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':');\n+\tGET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':');\n+\tGET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':');\n+\tGET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':');\n+\tGET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':');\n+\tGET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':');\n+\tGET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm);\n+\n+\t*end = in;\n+\n+\tv[0] = (addr[0] << 16) + addr[1];\n+\tv[1] = (addr[2] << 16) + addr[3];\n+\tv[2] = (addr[4] << 16) + addr[5];\n+\tv[3] = (addr[6] << 16) + addr[7];\n+\n+\treturn 0;\n+}\n+\n+static int\n+parse_ipv6_net(const char *in, struct rte_acl_field field[4])\n+{\n+\tint32_t rc;\n+\tconst char *mp;\n+\tuint32_t i, m, v[4];\n+\tconst uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT;\n+\n+\t/* get address. */\n+\trc = parse_ipv6_addr(in, &mp, v, '/');\n+\tif (rc != 0)\n+\t\treturn rc;\n+\n+\t/* get mask. */\n+\tGET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0);\n+\n+\t/* put all together. */\n+\tfor (i = 0; i != RTE_DIM(v); i++) {\n+\t\tif (m >= (i + 1) * nbu32)\n+\t\t\tfield[i].mask_range.u32 = nbu32;\n+\t\telse\n+\t\t\tfield[i].mask_range.u32 = m > (i * nbu32) ?\n+\t\t\t\tm - (i * 32) : 0;\n+\n+\t\tfield[i].value.u32 = v[i];\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+parse_cb_ipv6_rule(char *str, struct rte_acl_rule *v, int has_userdata)\n+{\n+\tint i, rc;\n+\tchar *s, *sp, *in[CB_FLD_NUM];\n+\tstatic const char *dlm = \" \\t\\n\";\n+\tint dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA;\n+\ts = str;\n+\n+\tfor (i = 0; i != dim; i++, s = NULL) {\n+\t\tin[i] = strtok_r(s, dlm, &sp);\n+\t\tif (in[i] == NULL)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\trc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6);\n+\tif (rc != 0) {\n+\t\tacl_log(\"failed to read source address/mask: %s\\n\",\n+\t\t\tin[CB_FLD_SRC_ADDR]);\n+\t\treturn rc;\n+\t}\n+\n+\trc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6);\n+\tif (rc != 0) {\n+\t\tacl_log(\"failed to read destination address/mask: %s\\n\",\n+\t\t\tin[CB_FLD_DST_ADDR]);\n+\t\treturn rc;\n+\t}\n+\n+\t/* source port. */\n+\tGET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],\n+\t\tv->field[SRCP_FIELD_IPV6].value.u16,\n+\t\t0, UINT16_MAX, 0);\n+\tGET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],\n+\t\tv->field[SRCP_FIELD_IPV6].mask_range.u16,\n+\t\t0, UINT16_MAX, 0);\n+\n+\tif (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,\n+\t\t\tsizeof(cb_port_delim)) != 0)\n+\t\treturn -EINVAL;\n+\n+\t/* destination port. */\n+\tGET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],\n+\t\tv->field[DSTP_FIELD_IPV6].value.u16,\n+\t\t0, UINT16_MAX, 0);\n+\tGET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],\n+\t\tv->field[DSTP_FIELD_IPV6].mask_range.u16,\n+\t\t0, UINT16_MAX, 0);\n+\n+\tif (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,\n+\t\t\tsizeof(cb_port_delim)) != 0)\n+\t\treturn -EINVAL;\n+\n+\tif (v->field[SRCP_FIELD_IPV6].mask_range.u16\n+\t\t\t< v->field[SRCP_FIELD_IPV6].value.u16\n+\t\t\t|| v->field[DSTP_FIELD_IPV6].mask_range.u16\n+\t\t\t< v->field[DSTP_FIELD_IPV6].value.u16)\n+\t\treturn -EINVAL;\n+\n+\tGET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8,\n+\t\t0, UINT8_MAX, '/');\n+\tGET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8,\n+\t\t0, UINT8_MAX, 0);\n+\n+\tif (has_userdata)\n+\t\tGET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata,\n+\t\t\t0, UINT32_MAX, 0);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Parse ClassBench rules file.\n+ * Expected format:\n+ * '@'<src_ipv4_addr>'/'<masklen> <space> \\\n+ * <dst_ipv4_addr>'/'<masklen> <space> \\\n+ * <src_port_low> <space> \":\" <src_port_high> <space> \\\n+ * <dst_port_low> <space> \":\" <dst_port_high> <space> \\\n+ * <proto>'/'<mask>\n+ */\n+static int\n+parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)\n+{\n+\tuint8_t a, b, c, d, m;\n+\n+\tGET_CB_FIELD(in, a, 0, UINT8_MAX, '.');\n+\tGET_CB_FIELD(in, b, 0, UINT8_MAX, '.');\n+\tGET_CB_FIELD(in, c, 0, UINT8_MAX, '.');\n+\tGET_CB_FIELD(in, d, 0, UINT8_MAX, '/');\n+\tGET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);\n+\n+\taddr[0] = IPv4(a, b, c, d);\n+\tmask_len[0] = m;\n+\n+\treturn 0;\n+}\n+\n+static int\n+parse_cb_ipv4vlan_rule(char *str, struct rte_acl_rule *v, int has_userdata)\n+{\n+\tint i, rc;\n+\tchar *s, *sp, *in[CB_FLD_NUM];\n+\tstatic const char *dlm = \" \\t\\n\";\n+\tint dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA;\n+\ts = str;\n+\n+\tfor (i = 0; i != dim; i++, s = NULL) {\n+\t\tin[i] = strtok_r(s, dlm, &sp);\n+\t\tif (in[i] == NULL)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\trc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],\n+\t\t\t&v->field[SRC_FIELD_IPV4].value.u32,\n+\t\t\t&v->field[SRC_FIELD_IPV4].mask_range.u32);\n+\tif (rc != 0) {\n+\t\tacl_log(\"failed to read source address/mask: %s\\n\",\n+\t\t\t\tin[CB_FLD_SRC_ADDR]);\n+\t\treturn rc;\n+\t}\n+\n+\trc = parse_ipv4_net(in[CB_FLD_DST_ADDR],\n+\t\t\t&v->field[DST_FIELD_IPV4].value.u32,\n+\t\t\t&v->field[DST_FIELD_IPV4].mask_range.u32);\n+\tif (rc != 0) {\n+\t\tacl_log(\"failed to read destination address/mask: %s\\n\",\n+\t\t\tin[CB_FLD_DST_ADDR]);\n+\t\treturn rc;\n+\t}\n+\n+\tGET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],\n+\t\tv->field[SRCP_FIELD_IPV4].value.u16,\n+\t\t0, UINT16_MAX, 0);\n+\tGET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],\n+\t\tv->field[SRCP_FIELD_IPV4].mask_range.u16,\n+\t\t0, UINT16_MAX, 0);\n+\n+\tif (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,\n+\t\t\tsizeof(cb_port_delim)) != 0)\n+\t\treturn -EINVAL;\n+\n+\tGET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],\n+\t\tv->field[DSTP_FIELD_IPV4].value.u16,\n+\t\t0, UINT16_MAX, 0);\n+\tGET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],\n+\t\tv->field[DSTP_FIELD_IPV4].mask_range.u16,\n+\t\t0, UINT16_MAX, 0);\n+\n+\tif (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,\n+\t\t\tsizeof(cb_port_delim)) != 0)\n+\t\treturn -EINVAL;\n+\n+\tif (v->field[SRCP_FIELD_IPV4].mask_range.u16\n+\t\t\t< v->field[SRCP_FIELD_IPV4].value.u16\n+\t\t\t|| v->field[DSTP_FIELD_IPV4].mask_range.u16\n+\t\t\t< v->field[DSTP_FIELD_IPV4].value.u16)\n+\t\treturn -EINVAL;\n+\n+\tGET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8,\n+\t\t0, UINT8_MAX, '/');\n+\tGET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8,\n+\t\t0, UINT8_MAX, 0);\n+\n+\tif (has_userdata)\n+\t\tGET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 0,\n+\t\t\tUINT32_MAX, 0);\n+\n+\treturn 0;\n+}\n+\n+static int\n+add_rules(const char *rule_path,\n+\t\tstruct rte_acl_rule **proute_base,\n+\t\tunsigned int *proute_num,\n+\t\tstruct rte_acl_rule **pacl_base,\n+\t\tunsigned int *pacl_num, uint32_t rule_size,\n+\t\tint (*parser)(char *, struct rte_acl_rule*, int))\n+{\n+\tuint8_t *acl_rules, *route_rules;\n+\tstruct rte_acl_rule *next;\n+\tunsigned int acl_num = 0, route_num = 0, total_num = 0;\n+\tunsigned int acl_cnt = 0, route_cnt = 0;\n+\tchar buff[LINE_MAX];\n+\tFILE *fh = fopen(rule_path, \"rb\");\n+\tunsigned int i = 0;\n+\n+\tif (fh == NULL)\n+\t\trte_exit(EXIT_FAILURE, \"%s: Open %s failed\\n\", __func__,\n+\t\t\trule_path);\n+\n+\twhile ((fgets(buff, LINE_MAX, fh) != NULL)) {\n+\t\tif (buff[0] == ROUTE_LEAD_CHAR)\n+\t\t\troute_num++;\n+\t\telse if (buff[0] == ACL_LEAD_CHAR)\n+\t\t\tacl_num++;\n+\t}\n+\n+\tif (route_num == 0)\n+\t\trte_exit(EXIT_FAILURE, \"Not find any route entries in %s!\\n\",\n+\t\t\t\trule_path);\n+\n+\tfseek(fh, 0, SEEK_SET);\n+\n+\tacl_rules = calloc(acl_num, rule_size);\n+\n+\tif (acl_rules == NULL)\n+\t\trte_exit(EXIT_FAILURE, \"%s: failed to malloc memory\\n\",\n+\t\t\t__func__);\n+\n+\troute_rules = calloc(route_num, rule_size);\n+\n+\tif (route_rules == NULL)\n+\t\trte_exit(EXIT_FAILURE, \"%s: failed to malloc memory\\n\",\n+\t\t\t__func__);\n+\n+\ti = 0;\n+\twhile (fgets(buff, LINE_MAX, fh) != NULL) {\n+\t\ti++;\n+\n+\t\tif (is_bypass_line(buff))\n+\t\t\tcontinue;\n+\n+\t\tchar s = buff[0];\n+\n+\t\t/* Route entry */\n+\t\tif (s == ROUTE_LEAD_CHAR)\n+\t\t\tnext = (struct rte_acl_rule *)(route_rules +\n+\t\t\t\troute_cnt * rule_size);\n+\n+\t\t/* ACL entry */\n+\t\telse if (s == ACL_LEAD_CHAR)\n+\t\t\tnext = (struct rte_acl_rule *)(acl_rules +\n+\t\t\t\tacl_cnt * rule_size);\n+\n+\t\t/* Illegal line */\n+\t\telse\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\"%s Line %u: should start with leading \"\n+\t\t\t\t\"char %c or %c\\n\",\n+\t\t\t\trule_path, i, ROUTE_LEAD_CHAR, ACL_LEAD_CHAR);\n+\n+\t\tif (parser(buff + 1, next, s == ROUTE_LEAD_CHAR) != 0)\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\"%s Line %u: parse rules error\\n\",\n+\t\t\t\trule_path, i);\n+\n+\t\tif (s == ROUTE_LEAD_CHAR) {\n+\t\t\t/* Check the forwarding port number */\n+\t\t\tif ((enabled_port_mask & (1 << next->data.userdata)) ==\n+\t\t\t\t\t0)\n+\t\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t\"%s Line %u: fwd number illegal:%u\\n\",\n+\t\t\t\t\trule_path, i, next->data.userdata);\n+\t\t\tnext->data.userdata += FWD_PORT_SHIFT;\n+\t\t\troute_cnt++;\n+\t\t} else {\n+\t\t\tnext->data.userdata = ACL_DENY_SIGNATURE + acl_cnt;\n+\t\t\tacl_cnt++;\n+\t\t}\n+\n+\t\tnext->data.priority = RTE_ACL_MAX_PRIORITY - total_num;\n+\t\tnext->data.category_mask = -1;\n+\t\ttotal_num++;\n+\t}\n+\n+\tfclose(fh);\n+\n+\t*pacl_base = (struct rte_acl_rule *)acl_rules;\n+\t*pacl_num = acl_num;\n+\t*proute_base = (struct rte_acl_rule *)route_rules;\n+\t*proute_num = route_cnt;\n+\n+\treturn 0;\n+}\n+\n+static void\n+dump_acl_config(void)\n+{\n+\tprintf(\"ACL option are:\\n\");\n+\tprintf(OPTION_RULE_IPV4\": %s\\n\", parm_config.rule_ipv4_name);\n+\tprintf(OPTION_RULE_IPV6\": %s\\n\", parm_config.rule_ipv6_name);\n+\tprintf(OPTION_SCALAR\": %d\\n\", parm_config.scalar);\n+}\n+\n+static int\n+check_acl_config(void)\n+{\n+\tif (parm_config.rule_ipv4_name == NULL) {\n+\t\tacl_log(\"ACL IPv4 rule file not specified\\n\");\n+\t\treturn -1;\n+\t} else if (parm_config.rule_ipv6_name == NULL) {\n+\t\tacl_log(\"ACL IPv6 rule file not specified\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static struct rte_acl_ctx*\n+app_acl_init(struct rte_acl_rule *route_base,\n+\t\tstruct rte_acl_rule *acl_base, unsigned int route_num,\n+\t\tunsigned int acl_num, int ipv6, int socketid)\n+{\n+\tchar name[PATH_MAX];\n+\tstruct rte_acl_param acl_param;\n+\tstruct rte_acl_config acl_build_param;\n+\tstruct rte_acl_ctx *context;\n+\tint dim = ipv6 ? RTE_DIM(ipv6_defs) : RTE_DIM(ipv4_defs);\n+\n+\t/* Create ACL contexts */\n+\tsnprintf(name, sizeof(name), \"%s%d\",\n+\t\t\tipv6 ? L3FWD_ACL_IPV6_NAME : L3FWD_ACL_IPV4_NAME,\n+\t\t\tsocketid);\n+\n+\tacl_param.name = name;\n+\tacl_param.socket_id = socketid;\n+\tacl_param.rule_size = RTE_ACL_RULE_SZ(dim);\n+\tacl_param.max_rule_num = MAX_ACL_RULE_NUM;\n+\n+\tcontext = rte_acl_create(&acl_param);\n+\n+\tif (context == NULL)\n+\t\trte_exit(EXIT_FAILURE, \"Failed to create ACL context\\n\");\n+\n+\tif (parm_config.scalar && rte_acl_set_ctx_classify(context,\n+\t\t\tRTE_ACL_CLASSIFY_SCALAR) != 0)\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"Failed to setup classify method for  ACL context\\n\");\n+\n+\tif (rte_acl_add_rules(context, route_base, route_num) < 0)\n+\t\trte_exit(EXIT_FAILURE, \"add rules failed\\n\");\n+\n+\tif (rte_acl_add_rules(context, acl_base, acl_num) < 0)\n+\t\trte_exit(EXIT_FAILURE, \"add rules failed\\n\");\n+\n+\t/* Perform builds */\n+\tmemset(&acl_build_param, 0, sizeof(acl_build_param));\n+\n+\tacl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;\n+\tacl_build_param.num_fields = dim;\n+\tmemcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs,\n+\t\tipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs));\n+\n+\tif (rte_acl_build(context, &acl_build_param) != 0)\n+\t\trte_exit(EXIT_FAILURE, \"Failed to build ACL trie\\n\");\n+\n+\trte_acl_dump(context);\n+\n+\treturn context;\n+}\n+\n+void\n+setup_acl(const int socket_id __attribute__((unused)))\n+{\n+\tunsigned int lcore_id;\n+\tunsigned int i;\n+\tint socketid;\n+\tstruct rte_acl_rule *acl_base_ipv4, *route_base_ipv4,\n+\t\t*acl_base_ipv6, *route_base_ipv6;\n+\tunsigned int acl_num_ipv4 = 0, route_num_ipv4 = 0,\n+\t\tacl_num_ipv6 = 0, route_num_ipv6 = 0;\n+\n+\tprintf(\"\\nsocket %d\\n\", socket_id);\n+\n+\tif (check_acl_config() != 0)\n+\t\trte_exit(EXIT_FAILURE, \"Failed to get valid ACL options\\n\");\n+\n+\tdump_acl_config();\n+\n+\t/* Load  rules from the input file */\n+\tif (add_rules(parm_config.rule_ipv4_name, &route_base_ipv4,\n+\t\t\t&route_num_ipv4, &acl_base_ipv4, &acl_num_ipv4,\n+\t\t\tsizeof(struct acl4_rule), &parse_cb_ipv4vlan_rule) < 0)\n+\t\trte_exit(EXIT_FAILURE, \"Failed to add rules\\n\");\n+\n+\tacl_log(\"IPv4 Route entries %u:\\n\", route_num_ipv4);\n+\tdump_ipv4_rules((struct acl4_rule *)route_base_ipv4, route_num_ipv4, 1);\n+\n+\tacl_log(\"IPv4 ACL entries %u:\\n\", acl_num_ipv4);\n+\tdump_ipv4_rules((struct acl4_rule *)acl_base_ipv4, acl_num_ipv4, 1);\n+\n+\tif (add_rules(parm_config.rule_ipv6_name, &route_base_ipv6,\n+\t\t\t&route_num_ipv6,\n+\t\t\t&acl_base_ipv6, &acl_num_ipv6,\n+\t\t\tsizeof(struct acl6_rule), &parse_cb_ipv6_rule) < 0)\n+\t\trte_exit(EXIT_FAILURE, \"Failed to add rules\\n\");\n+\n+\tacl_log(\"IPv6 Route entries %u:\\n\", route_num_ipv6);\n+\tdump_ipv6_rules((struct acl6_rule *)route_base_ipv6, route_num_ipv6, 1);\n+\n+\tacl_log(\"IPv6 ACL entries %u:\\n\", acl_num_ipv6);\n+\tdump_ipv6_rules((struct acl6_rule *)acl_base_ipv6, acl_num_ipv6, 1);\n+\n+\tmemset(&acl_config, 0, sizeof(acl_config));\n+\n+\t/* Check sockets a context should be created on */\n+\tif (!numa_on)\n+\t\tacl_config.mapped[0] = 1;\n+\telse {\n+\t\tfor (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n+\t\t\tif (rte_lcore_is_enabled(lcore_id) == 0)\n+\t\t\t\tcontinue;\n+\n+\t\t\tsocketid = rte_lcore_to_socket_id(lcore_id);\n+\t\t\tif (socketid >= NB_SOCKETS) {\n+\t\t\t\tacl_log(\"Socket %d of lcore %u is out \"\n+\t\t\t\t\t\"of range %d\\n\",\n+\t\t\t\t\tsocketid, lcore_id, NB_SOCKETS);\n+\t\t\t\tfree(route_base_ipv4);\n+\t\t\t\tfree(route_base_ipv6);\n+\t\t\t\tfree(acl_base_ipv4);\n+\t\t\t\tfree(acl_base_ipv6);\n+\t\t\t\treturn;\n+\t\t\t}\n+\n+\t\t\tacl_config.mapped[socketid] = 1;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < NB_SOCKETS; i++) {\n+\t\tif (acl_config.mapped[i]) {\n+\t\t\tacl_config.acx_ipv4[i] = app_acl_init(route_base_ipv4,\n+\t\t\t\tacl_base_ipv4, route_num_ipv4, acl_num_ipv4,\n+\t\t\t\t0, i);\n+\n+\t\t\tacl_config.acx_ipv6[i] = app_acl_init(route_base_ipv6,\n+\t\t\t\tacl_base_ipv6, route_num_ipv6, acl_num_ipv6,\n+\t\t\t\t1, i);\n+\t\t}\n+\t}\n+\n+\tfree(route_base_ipv4);\n+\tfree(route_base_ipv6);\n+\n+#ifdef L3FWDACL_DEBUG\n+\tacl_config.rule_ipv4 = (struct acl4_rule *)acl_base_ipv4;\n+\tacl_config.rule_ipv6 = (struct acl6_rule *)acl_base_ipv6;\n+#else\n+\tfree(acl_base_ipv4);\n+\tfree(acl_base_ipv6);\n+#endif\n+\n+}\n+\n+/* main processing loop */\n+int\n+acl_main_loop(__attribute__((unused)) void *dummy)\n+{\n+\tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n+\tunsigned int lcore_id;\n+\tuint64_t prev_tsc, diff_tsc, cur_tsc;\n+\tint i, nb_rx;\n+\tuint8_t portid, queueid;\n+\tstruct lcore_conf *qconf;\n+\tint socketid;\n+\tconst uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)\n+\t\t\t/ US_PER_S * BURST_TX_DRAIN_US;\n+\n+\tprev_tsc = 0;\n+\tlcore_id = rte_lcore_id();\n+\tqconf = &lcore_conf[lcore_id];\n+\tsocketid = rte_lcore_to_socket_id(lcore_id);\n+\n+\tif (qconf->n_rx_queue == 0) {\n+\t\tRTE_LOG(INFO, L3FWD, \"lcore %u has nothing to do\\n\", lcore_id);\n+\t\treturn 0;\n+\t}\n+\n+\tRTE_LOG(INFO, L3FWD, \"entering main loop on lcore %u\\n\", lcore_id);\n+\n+\tfor (i = 0; i < qconf->n_rx_queue; i++) {\n+\n+\t\tportid = qconf->rx_queue_list[i].port_id;\n+\t\tqueueid = qconf->rx_queue_list[i].queue_id;\n+\t\tRTE_LOG(INFO, L3FWD,\n+\t\t\t\" -- lcoreid=%u portid=%hhu rxqueueid=%hhu\\n\",\n+\t\t\tlcore_id, portid, queueid);\n+\t}\n+\n+\twhile (!force_quit) {\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+\t\t\tfor (i = 0; i < qconf->n_tx_port; ++i) {\n+\t\t\t\tportid = qconf->tx_port_id[i];\n+\t\t\t\trte_eth_tx_buffer_flush(portid,\n+\t\t\t\t\t\tqconf->tx_queue_id[portid],\n+\t\t\t\t\t\tqconf->tx_buffer[portid]);\n+\t\t\t}\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->n_rx_queue; ++i) {\n+\n+\t\t\tportid = qconf->rx_queue_list[i].port_id;\n+\t\t\tqueueid = qconf->rx_queue_list[i].queue_id;\n+\t\t\tnb_rx = rte_eth_rx_burst(portid, queueid,\n+\t\t\t\tpkts_burst, MAX_PKT_BURST);\n+\n+\t\t\tif (nb_rx > 0) {\n+\t\t\t\tstruct acl_search_t acl_search;\n+\n+\t\t\t\tl3fwd_acl_prepare_acl_parameter(pkts_burst,\n+\t\t\t\t\t\t\t&acl_search, nb_rx);\n+\n+\t\t\t\tif (acl_search.num_ipv4) {\n+\t\t\t\t\trte_acl_classify(\n+\t\t\t\t\t\tacl_config.acx_ipv4[socketid],\n+\t\t\t\t\t\tacl_search.data_ipv4,\n+\t\t\t\t\t\tacl_search.res_ipv4,\n+\t\t\t\t\t\tacl_search.num_ipv4,\n+\t\t\t\t\t\tDEFAULT_MAX_CATEGORIES);\n+\n+\t\t\t\t\tl3fwd_acl_send_packets(\n+\t\t\t\t\t\tacl_search.m_ipv4,\n+\t\t\t\t\t\tacl_search.res_ipv4,\n+\t\t\t\t\t\tacl_search.num_ipv4);\n+\t\t\t\t}\n+\n+\t\t\t\tif (acl_search.num_ipv6) {\n+\t\t\t\t\trte_acl_classify(\n+\t\t\t\t\t\tacl_config.acx_ipv6[socketid],\n+\t\t\t\t\t\tacl_search.data_ipv6,\n+\t\t\t\t\t\tacl_search.res_ipv6,\n+\t\t\t\t\t\tacl_search.num_ipv6,\n+\t\t\t\t\t\tDEFAULT_MAX_CATEGORIES);\n+\n+\t\t\t\t\tl3fwd_acl_send_packets(\n+\t\t\t\t\t\tacl_search.m_ipv6,\n+\t\t\t\t\t\tacl_search.res_ipv6,\n+\t\t\t\t\t\tacl_search.num_ipv6);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static inline void\n+acl_parse_ptype(struct rte_mbuf *m)\n+{\n+\tstruct ether_hdr *eth_hdr;\n+\tuint32_t packet_type = RTE_PTYPE_UNKNOWN;\n+\tuint16_t ether_type;\n+\tvoid *l3;\n+\tint hdr_len;\n+\tstruct ipv4_hdr *ipv4_hdr;\n+\tstruct ipv6_hdr *ipv6_hdr;\n+\n+\teth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);\n+\tether_type = eth_hdr->ether_type;\n+\tl3 = (uint8_t *)eth_hdr + sizeof(struct ether_hdr);\n+\tif (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {\n+\t\tipv4_hdr = (struct ipv4_hdr *)l3;\n+\t\thdr_len = (ipv4_hdr->version_ihl & IPV4_HDR_IHL_MASK) *\n+\t\t\t  IPV4_IHL_MULTIPLIER;\n+\t\tif (hdr_len == sizeof(struct ipv4_hdr)) {\n+\t\t\tpacket_type |= RTE_PTYPE_L3_IPV4;\n+\t\t\tif (ipv4_hdr->next_proto_id == IPPROTO_TCP)\n+\t\t\t\tpacket_type |= RTE_PTYPE_L4_TCP;\n+\t\t\telse if (ipv4_hdr->next_proto_id == IPPROTO_UDP)\n+\t\t\t\tpacket_type |= RTE_PTYPE_L4_UDP;\n+\t\t} else\n+\t\t\tpacket_type |= RTE_PTYPE_L3_IPV4_EXT;\n+\t} else if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {\n+\t\tipv6_hdr = (struct ipv6_hdr *)l3;\n+\t\tif (ipv6_hdr->proto == IPPROTO_TCP)\n+\t\t\tpacket_type |= RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP;\n+\t\telse if (ipv6_hdr->proto == IPPROTO_UDP)\n+\t\t\tpacket_type |= RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP;\n+\t\telse\n+\t\t\tpacket_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;\n+\t}\n+\n+\tm->packet_type = packet_type;\n+}\n+\n+uint16_t\n+acl_cb_parse_ptype(uint8_t port __rte_unused, uint16_t queue __rte_unused,\n+\t\t  struct rte_mbuf *pkts[], uint16_t nb_pkts,\n+\t\t  uint16_t max_pkts __rte_unused,\n+\t\t  void *user_param __rte_unused)\n+{\n+\tunsigned int i;\n+\n+\tfor (i = 0; i < nb_pkts; ++i)\n+\t\tacl_parse_ptype(pkts[i]);\n+\n+\treturn nb_pkts;\n+}\n+\n+/* Requirements:\n+ * 1. IP packets without extension;\n+ * 2. L4 payload should be either TCP or UDP.\n+ */\n+int\n+acl_check_ptype(int portid)\n+{\n+\tint i, ret;\n+\tint ptype_l3_ipv4_ext = 0;\n+\tint ptype_l3_ipv6_ext = 0;\n+\tint ptype_l4_tcp = 0;\n+\tint ptype_l4_udp = 0;\n+\tuint32_t ptype_mask = RTE_PTYPE_L3_MASK | RTE_PTYPE_L4_MASK;\n+\n+\tret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, NULL, 0);\n+\tif (ret <= 0)\n+\t\treturn 0;\n+\n+\tuint32_t ptypes[ret];\n+\n+\tret = rte_eth_dev_get_supported_ptypes(portid, ptype_mask, ptypes, ret);\n+\tfor (i = 0; i < ret; ++i) {\n+\t\tswitch (ptypes[i]) {\n+\t\tcase RTE_PTYPE_L3_IPV4_EXT:\n+\t\t\tptype_l3_ipv4_ext = 1;\n+\t\t\tbreak;\n+\t\tcase RTE_PTYPE_L3_IPV6_EXT:\n+\t\t\tptype_l3_ipv6_ext = 1;\n+\t\t\tbreak;\n+\t\tcase RTE_PTYPE_L4_TCP:\n+\t\t\tptype_l4_tcp = 1;\n+\t\t\tbreak;\n+\t\tcase RTE_PTYPE_L4_UDP:\n+\t\t\tptype_l4_udp = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (ptype_l3_ipv4_ext == 0)\n+\t\tprintf(\"port %d cannot parse RTE_PTYPE_L3_IPV4_EXT\\n\", portid);\n+\tif (ptype_l3_ipv6_ext == 0)\n+\t\tprintf(\"port %d cannot parse RTE_PTYPE_L3_IPV6_EXT\\n\", portid);\n+\tif (!ptype_l3_ipv4_ext || !ptype_l3_ipv6_ext)\n+\t\treturn 0;\n+\n+\tif (ptype_l4_tcp == 0)\n+\t\tprintf(\"port %d cannot parse RTE_PTYPE_L4_TCP\\n\", portid);\n+\tif (ptype_l4_udp == 0)\n+\t\tprintf(\"port %d cannot parse RTE_PTYPE_L4_UDP\\n\", portid);\n+\tif (ptype_l4_tcp && ptype_l4_udp)\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n+/* Not used by L3fwd ACL. */\n+void *\n+acl_get_ipv4_l3fwd_lookup_struct(__attribute__((unused)) const int socketid)\n+{\n+\treturn NULL;\n+}\n+\n+void *\n+acl_get_ipv6_l3fwd_lookup_struct(__attribute__((unused)) const int socketid)\n+{\n+\treturn NULL;\n+}\ndiff --git a/examples/l3fwd/l3fwd_acl.h b/examples/l3fwd/l3fwd_acl.h\nnew file mode 100644\nindex 0000000..b79784b\n--- /dev/null\n+++ b/examples/l3fwd/l3fwd_acl.h\n@@ -0,0 +1,263 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2016 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+#ifndef __L3FWD_ACL_H__\n+#define __L3FWD_ACL_H__\n+\n+#define MAX_ACL_RULE_NUM\t100000\n+#define DEFAULT_MAX_CATEGORIES\t1\n+#define L3FWD_ACL_IPV4_NAME\t\"l3fwd-acl-ipv4\"\n+#define L3FWD_ACL_IPV6_NAME\t\"l3fwd-acl-ipv6\"\n+#define ACL_DENY_SIGNATURE\t0xf0000000\n+#define RTE_LOGTYPE_L3FWDACL\tRTE_LOGTYPE_USER3\n+#define acl_log(format, ...)\tRTE_LOG(ERR, L3FWDACL, format, ##__VA_ARGS__)\n+#define uint32_t_to_char(ip, a, b, c, d) do {\\\n+\t\t*a = (unsigned char)(ip >> 24 & 0xff);\\\n+\t\t*b = (unsigned char)(ip >> 16 & 0xff);\\\n+\t\t*c = (unsigned char)(ip >> 8 & 0xff);\\\n+\t\t*d = (unsigned char)(ip & 0xff);\\\n+\t} while (0)\n+#define OFF_ETHHEAD\t(sizeof(struct ether_hdr))\n+#define OFF_IPV42PROTO (offsetof(struct ipv4_hdr, next_proto_id))\n+#define OFF_IPV62PROTO (offsetof(struct ipv6_hdr, proto))\n+#define MBUF_IPV4_2PROTO(m)\t\\\n+\trte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV42PROTO)\n+#define MBUF_IPV6_2PROTO(m)\t\\\n+\trte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV62PROTO)\n+\n+#define GET_CB_FIELD(in, fd, base, lim, dlm)\tdo {            \\\n+\tunsigned long val;                                      \\\n+\tchar *end;                                              \\\n+\terrno = 0;                                              \\\n+\tval = strtoul((in), &end, (base));                      \\\n+\tif (errno != 0 || end[0] != (dlm) || val > (lim))       \\\n+\t\treturn -EINVAL;                               \\\n+\t(fd) = (typeof(fd))val;                                 \\\n+\t(in) = end + 1;                                         \\\n+} while (0)\n+\n+/*\n+ * ACL rules should have higher priorities than route ones to ensure ACL rule\n+ * always be found when input packets have multi-matches in the database.\n+ * A exception case is performance measure, which can define route rules with\n+ * higher priority and route rules will always be returned in each lookup.\n+ * Reserve range from ACL_RULE_PRIORITY_MAX + 1 to\n+ * RTE_ACL_MAX_PRIORITY for route entries in performance measure\n+ */\n+#define ACL_RULE_PRIORITY_MAX 0x10000000\n+\n+/*\n+ * Forward port info save in ACL lib starts from 1\n+ * since ACL assume 0 is invalid.\n+ * So, need add 1 when saving and minus 1 when forwarding packets.\n+ */\n+#define FWD_PORT_SHIFT 1\n+\n+static inline void\n+print_one_ipv4_rule(struct acl4_rule *rule, int extra)\n+{\n+\tunsigned char a, b, c, d;\n+\n+\tuint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32,\n+\t\t\t&a, &b, &c, &d);\n+\tprintf(\"%hhu.%hhu.%hhu.%hhu/%u \", a, b, c, d,\n+\t\t\trule->field[SRC_FIELD_IPV4].mask_range.u32);\n+\tuint32_t_to_char(rule->field[DST_FIELD_IPV4].value.u32,\n+\t\t\t&a, &b, &c, &d);\n+\tprintf(\"%hhu.%hhu.%hhu.%hhu/%u \", a, b, c, d,\n+\t\t\trule->field[DST_FIELD_IPV4].mask_range.u32);\n+\tprintf(\"%hu : %hu %hu : %hu 0x%hhx/0x%hhx \",\n+\t\trule->field[SRCP_FIELD_IPV4].value.u16,\n+\t\trule->field[SRCP_FIELD_IPV4].mask_range.u16,\n+\t\trule->field[DSTP_FIELD_IPV4].value.u16,\n+\t\trule->field[DSTP_FIELD_IPV4].mask_range.u16,\n+\t\trule->field[PROTO_FIELD_IPV4].value.u8,\n+\t\trule->field[PROTO_FIELD_IPV4].mask_range.u8);\n+\tif (extra)\n+\t\tprintf(\"0x%x-0x%x-0x%x \",\n+\t\t\trule->data.category_mask,\n+\t\t\trule->data.priority,\n+\t\t\trule->data.userdata);\n+}\n+\n+static inline void\n+print_one_ipv6_rule(struct acl6_rule *rule, int extra)\n+{\n+\tunsigned char a, b, c, d;\n+\n+\tuint32_t_to_char(rule->field[SRC1_FIELD_IPV6].value.u32,\n+\t\t&a, &b, &c, &d);\n+\tprintf(\"%.2x%.2x:%.2x%.2x\", a, b, c, d);\n+\tuint32_t_to_char(rule->field[SRC2_FIELD_IPV6].value.u32,\n+\t\t&a, &b, &c, &d);\n+\tprintf(\":%.2x%.2x:%.2x%.2x\", a, b, c, d);\n+\tuint32_t_to_char(rule->field[SRC3_FIELD_IPV6].value.u32,\n+\t\t&a, &b, &c, &d);\n+\tprintf(\":%.2x%.2x:%.2x%.2x\", a, b, c, d);\n+\tuint32_t_to_char(rule->field[SRC4_FIELD_IPV6].value.u32,\n+\t\t&a, &b, &c, &d);\n+\tprintf(\":%.2x%.2x:%.2x%.2x/%u \", a, b, c, d,\n+\t\t\trule->field[SRC1_FIELD_IPV6].mask_range.u32\n+\t\t\t+ rule->field[SRC2_FIELD_IPV6].mask_range.u32\n+\t\t\t+ rule->field[SRC3_FIELD_IPV6].mask_range.u32\n+\t\t\t+ rule->field[SRC4_FIELD_IPV6].mask_range.u32);\n+\n+\tuint32_t_to_char(rule->field[DST1_FIELD_IPV6].value.u32,\n+\t\t&a, &b, &c, &d);\n+\tprintf(\"%.2x%.2x:%.2x%.2x\", a, b, c, d);\n+\tuint32_t_to_char(rule->field[DST2_FIELD_IPV6].value.u32,\n+\t\t&a, &b, &c, &d);\n+\tprintf(\":%.2x%.2x:%.2x%.2x\", a, b, c, d);\n+\tuint32_t_to_char(rule->field[DST3_FIELD_IPV6].value.u32,\n+\t\t&a, &b, &c, &d);\n+\tprintf(\":%.2x%.2x:%.2x%.2x\", a, b, c, d);\n+\tuint32_t_to_char(rule->field[DST4_FIELD_IPV6].value.u32,\n+\t\t&a, &b, &c, &d);\n+\tprintf(\":%.2x%.2x:%.2x%.2x/%u \", a, b, c, d,\n+\t\t\trule->field[DST1_FIELD_IPV6].mask_range.u32\n+\t\t\t+ rule->field[DST2_FIELD_IPV6].mask_range.u32\n+\t\t\t+ rule->field[DST3_FIELD_IPV6].mask_range.u32\n+\t\t\t+ rule->field[DST4_FIELD_IPV6].mask_range.u32);\n+\n+\tprintf(\"%hu : %hu %hu : %hu 0x%hhx/0x%hhx \",\n+\t\trule->field[SRCP_FIELD_IPV6].value.u16,\n+\t\trule->field[SRCP_FIELD_IPV6].mask_range.u16,\n+\t\trule->field[DSTP_FIELD_IPV6].value.u16,\n+\t\trule->field[DSTP_FIELD_IPV6].mask_range.u16,\n+\t\trule->field[PROTO_FIELD_IPV6].value.u8,\n+\t\trule->field[PROTO_FIELD_IPV6].mask_range.u8);\n+\tif (extra)\n+\t\tprintf(\"0x%x-0x%x-0x%x \",\n+\t\t\trule->data.category_mask,\n+\t\t\trule->data.priority,\n+\t\t\trule->data.userdata);\n+}\n+\n+/* Bypass comment and empty lines */\n+static inline int\n+is_bypass_line(char *buff)\n+{\n+\tint i = 0;\n+\n+\t/* comment line */\n+\tif (buff[0] == COMMENT_LEAD_CHAR)\n+\t\treturn 1;\n+\t/* empty line */\n+\twhile (buff[i] != '\\0') {\n+\t\tif (!isspace(buff[i]))\n+\t\t\treturn 0;\n+\t\ti++;\n+\t}\n+\treturn 1;\n+}\n+\n+#ifdef L3FWDACL_DEBUG\n+static inline void\n+dump_acl4_rule(struct rte_mbuf *m, uint32_t sig)\n+{\n+\tuint32_t offset = sig & ~ACL_DENY_SIGNATURE;\n+\tunsigned char a, b, c, d;\n+\tstruct ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset(m,\n+\t\t\t\t\t    struct ipv4_hdr *,\n+\t\t\t\t\t    sizeof(struct ether_hdr));\n+\n+\tuint32_t_to_char(rte_bswap32(ipv4_hdr->src_addr), &a, &b, &c, &d);\n+\tprintf(\"Packet Src:%hhu.%hhu.%hhu.%hhu \", a, b, c, d);\n+\tuint32_t_to_char(rte_bswap32(ipv4_hdr->dst_addr), &a, &b, &c, &d);\n+\tprintf(\"Dst:%hhu.%hhu.%hhu.%hhu \", a, b, c, d);\n+\n+\tprintf(\"Src port:%hu,Dst port:%hu \",\n+\t\t\trte_bswap16(*(uint16_t *)(ipv4_hdr + 1)),\n+\t\t\trte_bswap16(*((uint16_t *)(ipv4_hdr + 1) + 1)));\n+\tprintf(\"hit ACL %d - \", offset);\n+\n+\tprint_one_ipv4_rule(acl_config.rule_ipv4 + offset, 1);\n+\n+\tprintf(\"\\n\\n\");\n+}\n+\n+static inline void\n+dump_acl6_rule(struct rte_mbuf *m, uint32_t sig)\n+{\n+\tunsigned int i;\n+\tuint32_t offset = sig & ~ACL_DENY_SIGNATURE;\n+\tstruct ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset(m,\n+\t\t\t\t\t    struct ipv6_hdr *,\n+\t\t\t\t\t    sizeof(struct ether_hdr));\n+\n+\tprintf(\"Packet Src\");\n+\tfor (i = 0; i < RTE_DIM(ipv6_hdr->src_addr); i += sizeof(uint16_t))\n+\t\tprintf(\":%.2x%.2x\",\n+\t\t\tipv6_hdr->src_addr[i], ipv6_hdr->src_addr[i + 1]);\n+\n+\tprintf(\"\\nDst\");\n+\tfor (i = 0; i < RTE_DIM(ipv6_hdr->dst_addr); i += sizeof(uint16_t))\n+\t\tprintf(\":%.2x%.2x\",\n+\t\t\tipv6_hdr->dst_addr[i], ipv6_hdr->dst_addr[i + 1]);\n+\n+\tprintf(\"\\nSrc port:%hu,Dst port:%hu \",\n+\t\t\trte_bswap16(*(uint16_t *)(ipv6_hdr + 1)),\n+\t\t\trte_bswap16(*((uint16_t *)(ipv6_hdr + 1) + 1)));\n+\tprintf(\"hit ACL %d - \", offset);\n+\n+\tprint_one_ipv6_rule(acl_config.rule_ipv6 + offset, 1);\n+\n+\tprintf(\"\\n\\n\");\n+}\n+#endif /* L3FWDACL_DEBUG */\n+\n+static inline void\n+dump_ipv4_rules(struct acl4_rule *rule, int num, int extra)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < num; i++, rule++) {\n+\t\tprintf(\"\\t%d:\", i + 1);\n+\t\tprint_one_ipv4_rule(rule, extra);\n+\t\tprintf(\"\\n\");\n+\t}\n+}\n+\n+static inline void\n+dump_ipv6_rules(struct acl6_rule *rule, int num, int extra)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < num; i++, rule++) {\n+\t\tprintf(\"\\t%d:\", i + 1);\n+\t\tprint_one_ipv6_rule(rule, extra);\n+\t\tprintf(\"\\n\");\n+\t}\n+}\n+\n+#endif /* __L3FWD_ACL_H__ */\ndiff --git a/examples/l3fwd/l3fwd_acl_scalar.h b/examples/l3fwd/l3fwd_acl_scalar.h\nnew file mode 100644\nindex 0000000..2ac02f5\n--- /dev/null\n+++ b/examples/l3fwd/l3fwd_acl_scalar.h\n@@ -0,0 +1,182 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2016 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+#ifndef __L3FWD_ACL_SCALAR_H__\n+#define __L3FWD_ACL_SCALAR_H__\n+\n+#ifdef DO_RFC_1812_CHECKS\n+static inline void\n+l3fwd_acl_prepare_one_packet(struct rte_mbuf **pkts_in,\n+\t\t\tstruct acl_search_t *acl,\n+\t\t\tint index)\n+{\n+\tstruct ipv4_hdr *ipv4_hdr;\n+\tstruct rte_mbuf *pkt = pkts_in[index];\n+\n+\tif (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {\n+\t\tipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct ipv4_hdr *,\n+\t\t\t\t\t\t   sizeof(struct ether_hdr));\n+\n+\t\t/* Check to make sure the packet is valid (RFC1812) */\n+\t\tif (is_valid_ipv4_pkt(ipv4_hdr, pkt->pkt_len) >= 0) {\n+\n+\t\t\t/* Update time to live and header checksum */\n+\t\t\t--(ipv4_hdr->time_to_live);\n+\t\t\t++(ipv4_hdr->hdr_checksum);\n+\n+\t\t\t/* Fill acl structure */\n+\t\t\tacl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);\n+\t\t\tacl->m_ipv4[(acl->num_ipv4)++] = pkt;\n+\n+\t\t} else {\n+\t\t\t/* Not a valid IPv4 packet */\n+\t\t\trte_pktmbuf_free(pkt);\n+\t\t}\n+\t} else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {\n+\t\t/* Fill acl structure */\n+\t\tacl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);\n+\t\tacl->m_ipv6[(acl->num_ipv6)++] = pkt;\n+\n+\t} else {\n+\t\t/* Unknown type, drop the packet */\n+\t\trte_pktmbuf_free(pkt);\n+\t}\n+}\n+\n+#else\n+static inline void\n+l3fwd_acl_prepare_one_packet(struct rte_mbuf **pkts_in,\n+\t\t\tstruct acl_search_t *acl, int index)\n+{\n+\tstruct rte_mbuf *pkt = pkts_in[index];\n+\n+\tif (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {\n+\t\t/* Fill acl structure */\n+\t\tacl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);\n+\t\tacl->m_ipv4[(acl->num_ipv4)++] = pkt;\n+\n+\t} else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {\n+\t\t/* Fill acl structure */\n+\t\tacl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);\n+\t\tacl->m_ipv6[(acl->num_ipv6)++] = pkt;\n+\t} else {\n+\t\t/* Unknown type, drop the packet */\n+\t\trte_pktmbuf_free(pkt);\n+\t}\n+}\n+#endif /* DO_RFC_1812_CHECKS */\n+\n+/* Enqueue a single packet, and send burst if queue is filled */\n+static inline void\n+l3fwd_acl_send_single_packet(struct rte_mbuf *m, uint8_t port)\n+{\n+\tuint32_t lcore_id;\n+\tstruct lcore_conf *qconf;\n+\n+\tlcore_id = rte_lcore_id();\n+\tqconf = &lcore_conf[lcore_id];\n+\trte_eth_tx_buffer(port, qconf->tx_queue_id[port],\n+\t\t\tqconf->tx_buffer[port], m);\n+}\n+\n+static inline void\n+l3fwd_acl_prepare_acl_parameter(struct rte_mbuf **pkts_in,\n+\t\t\t\tstruct acl_search_t *acl, int nb_rx)\n+{\n+\tint i;\n+\n+\tacl->num_ipv4 = 0;\n+\tacl->num_ipv6 = 0;\n+\n+\t/* Prefetch first packets */\n+\tfor (i = 0; i < PREFETCH_OFFSET && i < nb_rx; i++) {\n+\t\trte_prefetch0(rte_pktmbuf_mtod(\n+\t\t\t\tpkts_in[i], void *));\n+\t}\n+\n+\tfor (i = 0; i < (nb_rx - PREFETCH_OFFSET); i++) {\n+\t\trte_prefetch0(rte_pktmbuf_mtod(pkts_in[\n+\t\t\t\ti + PREFETCH_OFFSET], void *));\n+\t\tl3fwd_acl_prepare_one_packet(pkts_in, acl, i);\n+\t}\n+\n+\t/* Process left packets */\n+\tfor (; i < nb_rx; i++)\n+\t\tl3fwd_acl_prepare_one_packet(pkts_in, acl, i);\n+}\n+\n+static inline void\n+l3fwd_acl_send_one_packet(struct rte_mbuf *m, uint32_t res)\n+{\n+\tif (likely((res & ACL_DENY_SIGNATURE) == 0 && res != 0)) {\n+\t\t/* forward packets */\n+\t\tl3fwd_acl_send_single_packet(m,\n+\t\t\t\t(uint8_t)(res - FWD_PORT_SHIFT));\n+\t} else{\n+\t\t/* in the ACL list, drop it */\n+#ifdef L3FWDACL_DEBUG\n+\t\tif ((res & ACL_DENY_SIGNATURE) != 0) {\n+\t\t\tif (RTE_ETH_IS_IPV4_HDR(m->packet_type))\n+\t\t\t\tdump_acl4_rule(m, res);\n+\t\t\telse if (RTE_ETH_IS_IPV6_HDR(m->packet_type))\n+\t\t\t\tdump_acl6_rule(m, res);\n+\t\t}\n+#endif\n+\t\trte_pktmbuf_free(m);\n+\t}\n+}\n+\n+\n+static inline void\n+l3fwd_acl_send_packets(struct rte_mbuf **m, uint32_t *res, int num)\n+{\n+\tint i;\n+\n+\t/* Prefetch first packets */\n+\tfor (i = 0; i < PREFETCH_OFFSET && i < num; i++) {\n+\t\trte_prefetch0(rte_pktmbuf_mtod(\n+\t\t\t\tm[i], void *));\n+\t}\n+\n+\tfor (i = 0; i < (num - PREFETCH_OFFSET); i++) {\n+\t\trte_prefetch0(rte_pktmbuf_mtod(m[\n+\t\t\t\ti + PREFETCH_OFFSET], void *));\n+\t\tl3fwd_acl_send_one_packet(m[i], res[i]);\n+\t}\n+\n+\t/* Process left packets */\n+\tfor (; i < num; i++)\n+\t\tl3fwd_acl_send_one_packet(m[i], res[i]);\n+}\n+\n+#endif /*  __L3FWD_ACL_SCALAR_H__ */\ndiff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c\nindex 9cc4460..6fdabf7 100644\n--- a/examples/l3fwd/l3fwd_em.c\n+++ b/examples/l3fwd/l3fwd_em.c\n@@ -754,7 +754,7 @@ setup_hash(const int socketid)\n \t\trte_hash_create(&ipv4_l3fwd_hash_params);\n \tif (ipv4_l3fwd_em_lookup_struct[socketid] == NULL)\n \t\trte_exit(EXIT_FAILURE,\n-\t\t\t\"Unable to create the l3fwd hash on socket %d\\n\",\n+\t\t\t\"Unable to create the v4 hash on socket %d\\n\",\n \t\t\tsocketid);\n \n \t/* create ipv6 hash */\n@@ -765,13 +765,15 @@ setup_hash(const int socketid)\n \t\trte_hash_create(&ipv6_l3fwd_hash_params);\n \tif (ipv6_l3fwd_em_lookup_struct[socketid] == NULL)\n \t\trte_exit(EXIT_FAILURE,\n-\t\t\t\"Unable to create the l3fwd hash on socket %d\\n\",\n+\t\t\t\"Unable to create the v6 hash on socket %d\\n\",\n \t\t\tsocketid);\n \n \tif (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) {\n-\t\t/* For testing hash matching with a large number of flows we\n-\t\t * generate millions of IP 5-tuples with an incremented dst\n-\t\t * address to initialize the hash table. */\n+\t\t/* For testing hash matching with a large number\n+\t\t * of flows we generate millions of IP 5-tuples\n+\t\t * with an incremented dst address to initialize\n+\t\t * the hash table.\n+\t\t */\n \t\tif (ipv6 == 0) {\n \t\t\t/* populate the ipv4 hash */\n \t\t\tpopulate_ipv4_many_flow_into_table(\n@@ -781,7 +783,7 @@ setup_hash(const int socketid)\n \t\t\t/* populate the ipv6 hash */\n \t\t\tpopulate_ipv6_many_flow_into_table(\n \t\t\t\tipv6_l3fwd_em_lookup_struct[socketid],\n-\t\t\t\thash_entry_number);\n+\t\t\thash_entry_number);\n \t\t}\n \t} else {\n \t\t/*\ndiff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c\nindex f621269..ab31210 100644\n--- a/examples/l3fwd/l3fwd_lpm.c\n+++ b/examples/l3fwd/l3fwd_lpm.c\n@@ -209,7 +209,7 @@ setup_lpm(const int socketid)\n \t\t\trte_lpm_create(s, socketid, &config_ipv4);\n \tif (ipv4_l3fwd_lpm_lookup_struct[socketid] == NULL)\n \t\trte_exit(EXIT_FAILURE,\n-\t\t\t\"Unable to create the l3fwd LPM table on socket %d\\n\",\n+\t\t\t\"Unable to create v4 LPM table on socket %d\\n\",\n \t\t\tsocketid);\n \n \t/* populate the LPM table */\n@@ -221,14 +221,13 @@ setup_lpm(const int socketid)\n \t\t\tcontinue;\n \n \t\tret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],\n-\t\t\tipv4_l3fwd_lpm_route_array[i].ip,\n-\t\t\tipv4_l3fwd_lpm_route_array[i].depth,\n-\t\t\tipv4_l3fwd_lpm_route_array[i].if_out);\n+\t\t\t\tipv4_l3fwd_lpm_route_array[i].ip,\n+\t\t\t\tipv4_l3fwd_lpm_route_array[i].depth,\n+\t\t\t\tipv4_l3fwd_lpm_route_array[i].if_out);\n \n \t\tif (ret < 0) {\n \t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\"Unable to add entry %u to the l3fwd LPM table on socket %d\\n\",\n-\t\t\t\ti, socketid);\n+\t\t\t\t\"Unable to add entry %u to v4 LPM table on socket %d\\n\", i, socketid);\n \t\t}\n \n \t\tprintf(\"LPM: Adding route 0x%08x / %d (%d)\\n\",\n@@ -243,11 +242,11 @@ setup_lpm(const int socketid)\n \tconfig.max_rules = IPV6_L3FWD_LPM_MAX_RULES;\n \tconfig.number_tbl8s = IPV6_L3FWD_LPM_NUMBER_TBL8S;\n \tconfig.flags = 0;\n-\tipv6_l3fwd_lpm_lookup_struct[socketid] = rte_lpm6_create(s, socketid,\n-\t\t\t\t&config);\n+\tipv6_l3fwd_lpm_lookup_struct[socketid] =\n+\t\t\trte_lpm6_create(s, socketid, &config);\n \tif (ipv6_l3fwd_lpm_lookup_struct[socketid] == NULL)\n \t\trte_exit(EXIT_FAILURE,\n-\t\t\t\"Unable to create the l3fwd LPM table on socket %d\\n\",\n+\t\t\t\"Unable to create v6 LPM table on socket %d\\n\",\n \t\t\tsocketid);\n \n \t/* populate the LPM table */\n@@ -265,13 +264,11 @@ setup_lpm(const int socketid)\n \n \t\tif (ret < 0) {\n \t\t\trte_exit(EXIT_FAILURE,\n-\t\t\t\t\"Unable to add entry %u to the l3fwd LPM table on socket %d\\n\",\n-\t\t\t\ti, socketid);\n+\t\t\t\t\"Unable to add entry %u to the l3fwd LPM table on socket %d\\n\", i, socketid);\n \t\t}\n \n \t\tprintf(\"LPM: Adding route %s / %d (%d)\\n\",\n-\t\t\t\"IPV6\",\n-\t\t\tipv6_l3fwd_lpm_route_array[i].depth,\n+\t\t\t\"IPV6\", ipv6_l3fwd_lpm_route_array[i].depth,\n \t\t\tipv6_l3fwd_lpm_route_array[i].if_out);\n \t}\n }\ndiff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c\nindex a50d628..3f35762 100644\n--- a/examples/l3fwd/main.c\n+++ b/examples/l3fwd/main.c\n@@ -51,6 +51,7 @@\n #include <rte_memory.h>\n #include <rte_memcpy.h>\n #include <rte_memzone.h>\n+#include <rte_malloc.h>\n #include <rte_eal.h>\n #include <rte_per_lcore.h>\n #include <rte_launch.h>\n@@ -97,11 +98,12 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;\n /**< Ports set in promiscuous mode off by default. */\n static int promiscuous_on;\n \n-/* Select Longest-Prefix or Exact match. */\n+/* Select Longest-Prefix(aka LPM), Exact match(aka EM) or ACL. */\n static int l3fwd_lpm_on;\n static int l3fwd_em_on;\n+static int l3fwd_acl_on;\n \n-static int numa_on = 1; /**< NUMA is enabled by default. */\n+int numa_on = 1; /**< NUMA is enabled by default. */\n static int parse_ptype; /**< Parse packet type using rx callback, and */\n \t\t\t/**< disabled by default */\n \n@@ -172,7 +174,7 @@ static struct rte_eth_conf port_conf = {\n static struct rte_mempool * pktmbuf_pool[NB_SOCKETS];\n \n struct l3fwd_lkp_mode {\n-\tvoid  (*setup)(int);\n+\tvoid  (*setup)(const int);\n \tint   (*check_ptype)(int);\n \trte_rx_callback_fn cb_parse_ptype;\n \tint   (*main_loop)(void *);\n@@ -200,6 +202,15 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {\n \t.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,\n };\n \n+static struct l3fwd_lkp_mode l3fwd_acl_lkp = {\n+\t.setup                  = setup_acl,\n+\t.check_ptype\t\t= acl_check_ptype,\n+\t.cb_parse_ptype\t\t= acl_cb_parse_ptype,\n+\t.main_loop              = acl_main_loop,\n+\t.get_ipv4_lookup_struct = acl_get_ipv4_l3fwd_lookup_struct,\n+\t.get_ipv6_lookup_struct = acl_get_ipv6_l3fwd_lookup_struct,\n+};\n+\n /*\n  * Setup lookup methods for forwarding.\n  * Currently exact-match and longest-prefix-match\n@@ -211,8 +222,11 @@ setup_l3fwd_lookup_tables(void)\n \t/* Setup HASH lookup functions. */\n \tif (l3fwd_em_on)\n \t\tl3fwd_lkp = l3fwd_em_lkp;\n-\t/* Setup LPM lookup functions. */\n+\t/* Setup ACL lookup functions. */\n+\telse if (l3fwd_acl_on)\n+\t\tl3fwd_lkp = l3fwd_acl_lkp;\n \telse\n+\t/* Setup LPM lookup functions. */\n \t\tl3fwd_lkp = l3fwd_lpm_lkp;\n }\n \n@@ -312,31 +326,45 @@ print_usage(const char *prgname)\n {\n \tprintf(\"%s [EAL options] --\"\n \t\t\" -p PORTMASK\"\n+\t\t\"--\"OPTION_RULE_IPV4\"=FILE\"\n+\t\t\"--\"OPTION_RULE_IPV6\"=FILE\"\n \t\t\" [-P]\"\n \t\t\" [-E]\"\n+\t\t\" [-A]\"\n \t\t\" [-L]\"\n-\t\t\" --config (port,queue,lcore)[,(port,queue,lcore)]\"\n-\t\t\" [--eth-dest=X,MM:MM:MM:MM:MM:MM]\"\n-\t\t\" [--enable-jumbo [--max-pkt-len PKTLEN]]\"\n-\t\t\" [--no-numa]\"\n-\t\t\" [--hash-entry-num]\"\n-\t\t\" [--ipv6]\"\n-\t\t\" [--parse-ptype]\\n\\n\"\n+\t\t\" [--\"OPTION_CONFIG\" (port,queue,lcore)[,(port,queue,lcore]]\"\n+\t\t\" [--\"OPTION_ETH_DEST\" =X,MM:MM:MM:MM:MM:MM]\"\n+\t\t\" [--\"OPTION_ENBJMO\" [--\"OPTION_MAX_PKT_LEN\" PKTLEN]]\"\n+\t\t\" [--\"OPTION_NONUMA\"]\"\n+\t\t\" [--\"OPTION_HASH_ENTRY_NUM\"]\"\n+\t\t\" [--\"OPTION_IPV6\"]\"\n+\t\t\" [--\"OPTION_PARSE_PTYPE\"]\\n\\n\"\n \n \t\t\"  -p PORTMASK: Hexadecimal bitmask of ports to configure\\n\"\n \t\t\"  -P : Enable promiscuous mode\\n\"\n \t\t\"  -E : Enable exact match\\n\"\n+\t\t\"  -A : Enable access control list match\\n\"\n \t\t\"  -L : Enable longest prefix match (default)\\n\"\n-\t\t\"  --config (port,queue,lcore): Rx queue configuration\\n\"\n-\t\t\"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\\n\"\n-\t\t\"  --enable-jumbo: Enable jumbo frames\\n\"\n-\t\t\"  --max-pkt-len: Under the premise of enabling jumbo,\\n\"\n+\t\t\"  --\"OPTION_CONFIG\" (port,queue,lcore): Rx queue configuration\\n\"\n+\t\t\"  --\"OPTION_ETH_DEST\"=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\\n\"\n+\t\t\"  --\"OPTION_ENBJMO\": Enable jumbo frames\\n\"\n+\t\t\"  --\"OPTION_MAX_PKT_LEN\": Under the premise of enabling jumbo,\\n\"\n \t\t\"                 maximum packet length in decimal (64-9600)\\n\"\n-\t\t\"  --no-numa: Disable numa awareness\\n\"\n-\t\t\"  --hash-entry-num: Specify the hash entry number in hexadecimal to be setup\\n\"\n-\t\t\"  --ipv6: Set if running ipv6 packets\\n\"\n-\t\t\"  --parse-ptype: Set to use software to analyze packet type\\n\\n\",\n-\t\tprgname);\n+\t\t\"  --\"OPTION_NONUMA\": Disable numa awareness\\n\"\n+\t\t\"  --\"OPTION_HASH_ENTRY_NUM\": Specify the hash entry number in hexadecimal to be setup\\n\"\n+\t\t\"  --\"OPTION_IPV6\": Set if running ipv6 packets\\n\"\n+\t\t\"  --\"OPTION_PARSE_PTYPE\": Set to use software to analyze packet type\\n\\n\"\n+\t\t\"  --\"OPTION_RULE_IPV4\"=FILE: specify the ipv4 rules \"\n+\t\t\"entries file. \"\n+\t\t\"Each rule occupy one line. \"\n+\t\t\"2 kinds of rules are supported. \"\n+\t\t\"One is ACL entry at while line leads with character '%c', \"\n+\t\t\"another is route entry at while line leads with \"\n+\t\t\"character '%c'.\\n\"\n+\t\t\"  --\"OPTION_RULE_IPV6\"=FILE: specify the ipv6 rules \"\n+\t\t\"entries file.\\n\"\n+\t\t\"  --\"OPTION_SCALAR\": Use scalar function to do lookup\\n\",\n+\t\tprgname, ACL_LEAD_CHAR, ROUTE_LEAD_CHAR);\n }\n \n static int\n@@ -477,17 +505,11 @@ parse_eth_dest(const char *optarg)\n static const char short_options[] =\n \t\"p:\"  /* portmask */\n \t\"P\"   /* promiscuous */\n+\t\"A\"   /* enable access control list match */\n \t\"L\"   /* enable long prefix match */\n \t\"E\"   /* enable exact match */\n \t;\n \n-#define CMD_LINE_OPT_CONFIG \"config\"\n-#define CMD_LINE_OPT_ETH_DEST \"eth-dest\"\n-#define CMD_LINE_OPT_NO_NUMA \"no-numa\"\n-#define CMD_LINE_OPT_IPV6 \"ipv6\"\n-#define CMD_LINE_OPT_ENABLE_JUMBO \"enable-jumbo\"\n-#define CMD_LINE_OPT_HASH_ENTRY_NUM \"hash-entry-num\"\n-#define CMD_LINE_OPT_PARSE_PTYPE \"parse-ptype\"\n enum {\n \t/* long options mapped to a short option */\n \n@@ -501,16 +523,22 @@ enum {\n \tCMD_LINE_OPT_ENABLE_JUMBO_NUM,\n \tCMD_LINE_OPT_HASH_ENTRY_NUM_NUM,\n \tCMD_LINE_OPT_PARSE_PTYPE_NUM,\n+\tCMD_LINE_OPT_RULE_IPV4,\n+\tCMD_LINE_OPT_RULE_IPV6,\n+\tCMD_LINE_OPT_SCALAR,\n };\n \n static const struct option lgopts[] = {\n-\t{CMD_LINE_OPT_CONFIG, 1, 0, CMD_LINE_OPT_CONFIG_NUM},\n-\t{CMD_LINE_OPT_ETH_DEST, 1, 0, CMD_LINE_OPT_ETH_DEST_NUM},\n-\t{CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},\n-\t{CMD_LINE_OPT_IPV6, 0, 0, CMD_LINE_OPT_IPV6_NUM},\n-\t{CMD_LINE_OPT_ENABLE_JUMBO, 0, 0, CMD_LINE_OPT_ENABLE_JUMBO_NUM},\n-\t{CMD_LINE_OPT_HASH_ENTRY_NUM, 1, 0, CMD_LINE_OPT_HASH_ENTRY_NUM_NUM},\n-\t{CMD_LINE_OPT_PARSE_PTYPE, 0, 0, CMD_LINE_OPT_PARSE_PTYPE_NUM},\n+\t{OPTION_CONFIG, 1, 0, CMD_LINE_OPT_CONFIG_NUM},\n+\t{OPTION_ETH_DEST, 1, 0, CMD_LINE_OPT_ETH_DEST_NUM},\n+\t{OPTION_NONUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},\n+\t{OPTION_IPV6, 0, 0, CMD_LINE_OPT_IPV6_NUM},\n+\t{OPTION_ENBJMO, 0, 0, CMD_LINE_OPT_ENABLE_JUMBO_NUM},\n+\t{OPTION_HASH_ENTRY_NUM, 1, 0, CMD_LINE_OPT_HASH_ENTRY_NUM_NUM},\n+\t{OPTION_PARSE_PTYPE, 0, 0, CMD_LINE_OPT_PARSE_PTYPE_NUM},\n+\t{OPTION_RULE_IPV4, 1, 0, CMD_LINE_OPT_RULE_IPV4},\n+\t{OPTION_RULE_IPV6, 1, 0, CMD_LINE_OPT_RULE_IPV6},\n+\t{OPTION_SCALAR, 0, 0, CMD_LINE_OPT_SCALAR},\n \t{NULL, 0, 0, 0}\n };\n \n@@ -522,17 +550,17 @@ static const struct option lgopts[] = {\n  * value of 8192\n  */\n #define NB_MBUF RTE_MAX(\t\\\n-\t(nb_ports*nb_rx_queue*RTE_TEST_RX_DESC_DEFAULT +\t\\\n-\tnb_ports*nb_lcores*MAX_PKT_BURST +\t\t\t\\\n-\tnb_ports*n_tx_queue*RTE_TEST_TX_DESC_DEFAULT +\t\t\\\n-\tnb_lcores*MEMPOOL_CACHE_SIZE),\t\t\t\t\\\n+\t(nb_ports * nb_rx_queue * RTE_TEST_RX_DESC_DEFAULT +\t\\\n+\tnb_ports * nb_lcores * MAX_PKT_BURST +\t\t\t\\\n+\tnb_ports * n_tx_queue * RTE_TEST_TX_DESC_DEFAULT +\t\t\\\n+\tnb_lcores * MEMPOOL_CACHE_SIZE),\t\t\t\t\\\n \t(unsigned)8192)\n \n /* Parse the argument given in the command line of the application */\n static int\n parse_args(int argc, char **argv)\n {\n-\tint opt, ret;\n+\tint opt, ret, chk_cond;\n \tchar **argvopt;\n \tint option_index;\n \tchar *prgname = argv[0];\n@@ -544,17 +572,19 @@ parse_args(int argc, char **argv)\n \tconst char *str2 = \"L3FWD: Promiscuous mode selected\";\n \tconst char *str3 = \"L3FWD: Exact match selected\";\n \tconst char *str4 = \"L3FWD: Longest-prefix match selected\";\n-\tconst char *str5 = \"L3FWD: Invalid config\";\n-\tconst char *str6 = \"L3FWD: NUMA is disabled\";\n-\tconst char *str7 = \"L3FWD: IPV6 is specified\";\n-\tconst char *str8 =\n+\tconst char *str5 = \"L3FWD: Access Control List match selected\";\n+\tconst char *str6 = \"L3FWD: Invalid config\";\n+\tconst char *str7 = \"L3FWD: NUMA is disabled\";\n+\tconst char *str8 = \"L3FWD: IPV6 is specified\";\n+\tconst char *str9 =\n \t\t\"L3FWD: Jumbo frame is enabled - disabling simple TX path\";\n-\tconst char *str9 = \"L3FWD: Invalid packet length\";\n-\tconst char *str10 = \"L3FWD: Set jumbo frame max packet len to \";\n-\tconst char *str11 = \"L3FWD: Invalid hash entry number\";\n-\tconst char *str12 =\n-\t\t\"L3FWD: LPM and EM are mutually exclusive, select only one\";\n-\tconst char *str13 = \"L3FWD: LPM or EM none selected, default LPM on\";\n+\tconst char *str10 = \"L3FWD: Invalid packet length\";\n+\tconst char *str11 = \"L3FWD: Set jumbo frame max packet len to \";\n+\tconst char *str12 = \"L3FWD: Invalid hash entry number\";\n+\tconst char *str13 =\n+\t\t\"L3FWD: LPM, EM and ACL are mutually exclusive, select only one\";\n+\tconst char *str14 =\n+\t\t\"L3FWD: LPM, EM or ACL none selected, default LPM on\";\n \n \twhile ((opt = getopt_long(argc, argvopt, short_options,\n \t\t\t\tlgopts, &option_index)) != EOF) {\n@@ -585,11 +615,16 @@ parse_args(int argc, char **argv)\n \t\t\tl3fwd_lpm_on = 1;\n \t\t\tbreak;\n \n+\t\tcase 'A':\n+\t\t\tprintf(\"%s\\n\", str5);\n+\t\t\tl3fwd_acl_on = 1;\n+\t\t\tbreak;\n+\n \t\t/* long options */\n \t\tcase CMD_LINE_OPT_CONFIG_NUM:\n \t\t\tret = parse_config(optarg);\n \t\t\tif (ret) {\n-\t\t\t\tprintf(\"%s\\n\", str5);\n+\t\t\t\tprintf(\"%s\\n\", str6);\n \t\t\t\tprint_usage(prgname);\n \t\t\t\treturn -1;\n \t\t\t}\n@@ -600,12 +635,12 @@ parse_args(int argc, char **argv)\n \t\t\tbreak;\n \n \t\tcase CMD_LINE_OPT_NO_NUMA_NUM:\n-\t\t\tprintf(\"%s\\n\", str6);\n+\t\t\tprintf(\"%s\\n\", str7);\n \t\t\tnuma_on = 0;\n \t\t\tbreak;\n \n \t\tcase CMD_LINE_OPT_IPV6_NUM:\n-\t\t\tprintf(\"%sn\", str7);\n+\t\t\tprintf(\"%sn\", str8);\n \t\t\tipv6 = 1;\n \t\t\tbreak;\n \n@@ -614,7 +649,7 @@ parse_args(int argc, char **argv)\n \t\t\t\t\"max-pkt-len\", required_argument, 0, 0\n \t\t\t};\n \n-\t\t\tprintf(\"%s\\n\", str8);\n+\t\t\tprintf(\"%s\\n\", str9);\n \t\t\tport_conf.rxmode.jumbo_frame = 1;\n \n \t\t\t/*\n@@ -626,13 +661,13 @@ parse_args(int argc, char **argv)\n \t\t\t\tret = parse_max_pkt_len(optarg);\n \t\t\t\tif ((ret < 64) ||\n \t\t\t\t\t(ret > MAX_JUMBO_PKT_LEN)) {\n-\t\t\t\t\tprintf(\"%s\\n\", str9);\n+\t\t\t\t\tprintf(\"%s\\n\", str10);\n \t\t\t\t\tprint_usage(prgname);\n \t\t\t\t\treturn -1;\n \t\t\t\t}\n \t\t\t\tport_conf.rxmode.max_rx_pkt_len = ret;\n \t\t\t}\n-\t\t\tprintf(\"%s %u\\n\", str10,\n+\t\t\tprintf(\"%s %u\\n\", str11,\n \t\t\t\t(unsigned int)port_conf.rxmode.max_rx_pkt_len);\n \t\t\tbreak;\n \t\t}\n@@ -642,7 +677,7 @@ parse_args(int argc, char **argv)\n \t\t\tif ((ret > 0) && (ret <= L3FWD_HASH_ENTRIES)) {\n \t\t\t\thash_entry_number = ret;\n \t\t\t} else {\n-\t\t\t\tprintf(\"%s\\n\", str11);\n+\t\t\t\tprintf(\"%s\\n\", str12);\n \t\t\t\tprint_usage(prgname);\n \t\t\t\treturn -1;\n \t\t\t}\n@@ -653,15 +688,29 @@ parse_args(int argc, char **argv)\n \t\t\tparse_ptype = 1;\n \t\t\tbreak;\n \n+\t\tcase CMD_LINE_OPT_RULE_IPV4:\n+\t\t\tl3fwd_acl_set_rule_ipv4_name(optarg);\n+\t\t\tbreak;\n+\n+\t\tcase CMD_LINE_OPT_RULE_IPV6:\n+\t\t\tl3fwd_acl_set_rule_ipv6_name(optarg);\n+\t\t\tbreak;\n+\n+\t\tcase CMD_LINE_OPT_SCALAR:\n+\t\t\tl3fwd_acl_set_scalar();\n+\t\t\tbreak;\n+\n \t\tdefault:\n \t\t\tprint_usage(prgname);\n \t\t\treturn -1;\n \t\t}\n \t}\n \n-\t/* If both LPM and EM are selected, return error. */\n-\tif (l3fwd_lpm_on && l3fwd_em_on) {\n-\t\tprintf(\"%s\\n\", str12);\n+\t/* If more than one(LPM, EM and ACL) are selected, return error. */\n+\tchk_cond = l3fwd_lpm_on ? (l3fwd_em_on || l3fwd_acl_on) :\n+\t\t\t\t(l3fwd_em_on && l3fwd_acl_on);\n+\tif (chk_cond) {\n+\t\tprintf(\"%s\\n\", str13);\n \t\treturn -1;\n \t}\n \n@@ -669,9 +718,9 @@ parse_args(int argc, char **argv)\n \t * Nothing is selected, pick longest-prefix match\n \t * as default match.\n \t */\n-\tif (!l3fwd_lpm_on && !l3fwd_em_on) {\n+\tif (!l3fwd_lpm_on && !l3fwd_em_on && !l3fwd_acl_on) {\n \t\tl3fwd_lpm_on = 1;\n-\t\tprintf(\"%s\\n\", str13);\n+\t\tprintf(\"%s\\n\", str14);\n \t}\n \n \t/*\n@@ -684,6 +733,11 @@ parse_args(int argc, char **argv)\n \t\thash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;\n \t}\n \n+\t/* For ACL, update port config rss hash filter. */\n+\tif (l3fwd_acl_on)\n+\t\tport_conf.rx_adv_conf.rss_conf.rss_hf |=\n+\t\t\tETH_RSS_UDP | ETH_RSS_TCP | ETH_RSS_SCTP;\n+\n \tif (optind >= 0)\n \t\targv[optind-1] = prgname;\n \n@@ -737,8 +791,9 @@ init_mem(unsigned nb_mbuf)\n \t\t\t\tprintf(\"Allocated mbuf pool on socket %d\\n\",\n \t\t\t\t\tsocketid);\n \n-\t\t\t/* Setup either LPM or EM(f.e Hash).  */\n-\t\t\tl3fwd_lkp.setup(socketid);\n+\t\t\t/* Setup LPM/EM (f.e. Hash) functions */\n+\t\t\tif (l3fwd_lpm_on || l3fwd_em_on)\n+\t\t\t\tl3fwd_lkp.setup(socketid);\n \t\t}\n \t\tqconf = &lcore_conf[lcore_id];\n \t\tqconf->ipv4_lookup_struct =\n@@ -836,7 +891,7 @@ prepare_ptype_parser(uint8_t portid, uint16_t queueid)\n \t\treturn 1;\n \n \tprintf(\"port %d cannot parse packet type, please add --%s\\n\",\n-\t       portid, CMD_LINE_OPT_PARSE_PTYPE);\n+\t       portid, OPTION_PARSE_PTYPE);\n \treturn 0;\n }\n \n@@ -893,6 +948,10 @@ main(int argc, char **argv)\n \t/* Setup function pointers for lookup method. */\n \tsetup_l3fwd_lookup_tables();\n \n+\t/* Setup ACL functions */\n+\tif (l3fwd_acl_on)\n+\t\tl3fwd_lkp.setup(-1);\n+\n \t/* initialize all ports */\n \tfor (portid = 0; portid < nb_ports; portid++) {\n \t\t/* skip ports that are not enabled */\n@@ -936,6 +995,28 @@ main(int argc, char **argv)\n \t\tif (ret < 0)\n \t\t\trte_exit(EXIT_FAILURE, \"init_mem failed\\n\");\n \n+\t\t/* ACL specific. */\n+\t\tif (l3fwd_acl_on) {\n+\t\t\tfor (lcore_id = 0;\n+\t\t\t\tlcore_id < RTE_MAX_LCORE; lcore_id++) {\n+\t\t\t\tif (rte_lcore_is_enabled(lcore_id) == 0)\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\t/* Initialize TX buffers */\n+\t\t\t\tqconf = &lcore_conf[lcore_id];\n+\t\t\t\tqconf->tx_buffer[portid] =\n+\t\t\t\t\trte_zmalloc_socket(\"tx_buffer\",\n+\t\t\t\t\tRTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST),\n+\t\t\t\t\t0, rte_eth_dev_socket_id(portid));\n+\n+\t\t\t\tif (qconf->tx_buffer[portid] == NULL)\n+\t\t\t\t\trte_exit(EXIT_FAILURE, \"Can't allocate tx buffer for port %u\\n\", (unsigned int) portid);\n+\n+\t\t\t\trte_eth_tx_buffer_init(qconf->tx_buffer[portid],\n+\t\t\t\t\t\t\tMAX_PKT_BURST);\n+\t\t\t}\n+\t\t}\n+\n \t\t/* init one TX queue per couple (lcore,port) */\n \t\tqueueid = 0;\n \t\tfor (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n",
    "prefixes": [
        "dpdk-dev",
        "v4",
        "1/3"
    ]
}