get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 114624,
    "url": "http://patches.dpdk.org/api/patches/114624/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220804165839.1074817-3-cristian.dumitrescu@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20220804165839.1074817-3-cristian.dumitrescu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220804165839.1074817-3-cristian.dumitrescu@intel.com",
    "date": "2022-08-04T16:58:20",
    "name": "[02/21] net/softnic: remove flow support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "6889e24b64d54ed0fb17defbd334502263cb2ed3",
    "submitter": {
        "id": 19,
        "url": "http://patches.dpdk.org/api/people/19/?format=api",
        "name": "Cristian Dumitrescu",
        "email": "cristian.dumitrescu@intel.com"
    },
    "delegate": {
        "id": 3961,
        "url": "http://patches.dpdk.org/api/users/3961/?format=api",
        "username": "arybchenko",
        "first_name": "Andrew",
        "last_name": "Rybchenko",
        "email": "andrew.rybchenko@oktetlabs.ru"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20220804165839.1074817-3-cristian.dumitrescu@intel.com/mbox/",
    "series": [
        {
            "id": 24205,
            "url": "http://patches.dpdk.org/api/series/24205/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=24205",
            "date": "2022-08-04T16:58:18",
            "name": "net/softnic: replace the legacy pipeline with SWX pipeline",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/24205/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/114624/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/114624/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 8C701A00C4;\n\tThu,  4 Aug 2022 18:58:59 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 01CD142BCA;\n\tThu,  4 Aug 2022 18:58:56 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n by mails.dpdk.org (Postfix) with ESMTP id A02BE4067C\n for <dev@dpdk.org>; Thu,  4 Aug 2022 18:58:52 +0200 (CEST)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 04 Aug 2022 09:58:46 -0700",
            "from silpixa00400573.ir.intel.com (HELO\n silpixa00400573.ger.corp.intel.com) ([10.237.223.157])\n by orsmga001.jf.intel.com with ESMTP; 04 Aug 2022 09:58:44 -0700"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1659632332; x=1691168332;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=uujgay7c9l4lHgKBaTPTUY7SnW5GFO3leLkIri2gFqo=;\n b=GwEhj6r8HcsOKQEUSaKyNMPRGOwpqmag4nuyXS18lB0Xifbqca1nq211\n LefM3yz/Oe+Jy3YjIBIqj4fSAEgkoHpyFjP6vckP2DqvgbGUJ6n4/IKzs\n G7pw195Zqu1adP2Bf98drld/7ydCLCak7piO10HVJ4K4vQn0fFS6q8c6H\n Nu47L5eLh4BQg91pI1LB79TeptgOl5SOy0yKop120r5/PIunvFtBFUGHS\n cLL3C0qQ8jGdCHh9Co0sz52V+AZYVwT4nJSGRnrm6nmPnczm6Y1S1u+OB\n FyAyyA088kla4A54pdSf4d2F3qoQJ2jdUK7q1FTXQFRdr+/wGX9cIDjub A==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6400,9594,10429\"; a=\"290000087\"",
            "E=Sophos;i=\"5.93,216,1654585200\"; d=\"scan'208\";a=\"290000087\"",
            "E=Sophos;i=\"5.93,216,1654585200\"; d=\"scan'208\";a=\"636163087\""
        ],
        "X-ExtLoop1": "1",
        "From": "Cristian Dumitrescu <cristian.dumitrescu@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "jasvinder.singh@intel.com,\n\tyogesh.jangra@intel.com",
        "Subject": "[PATCH 02/21] net/softnic: remove flow support",
        "Date": "Thu,  4 Aug 2022 16:58:20 +0000",
        "Message-Id": "<20220804165839.1074817-3-cristian.dumitrescu@intel.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20220804165839.1074817-1-cristian.dumitrescu@intel.com>",
        "References": "<20220804165839.1074817-1-cristian.dumitrescu@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Remove the Ethernet device flow API support.\n\nSigned-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>\nSigned-off-by: Yogesh Jangra <yogesh.jangra@intel.com>\n---\n drivers/net/softnic/meson.build            |    1 -\n drivers/net/softnic/rte_eth_softnic.c      |    9 -\n drivers/net/softnic/rte_eth_softnic_cli.c  |   81 -\n drivers/net/softnic/rte_eth_softnic_flow.c | 2293 --------------------\n 4 files changed, 2384 deletions(-)\n delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c",
    "diff": "diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build\nindex e2dbd6166e..4ebe60921c 100644\n--- a/drivers/net/softnic/meson.build\n+++ b/drivers/net/softnic/meson.build\n@@ -13,7 +13,6 @@ sources = files(\n         'rte_eth_softnic_action.c',\n         'rte_eth_softnic_cli.c',\n         'rte_eth_softnic_cryptodev.c',\n-        'rte_eth_softnic_flow.c',\n         'rte_eth_softnic_link.c',\n         'rte_eth_softnic_mempool.c',\n         'rte_eth_softnic_meter.c',\ndiff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c\nindex ae3e8b3bcd..8e361adbad 100644\n--- a/drivers/net/softnic/rte_eth_softnic.c\n+++ b/drivers/net/softnic/rte_eth_softnic.c\n@@ -215,14 +215,6 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,\n \treturn 0;\n }\n \n-static int\n-pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n-\t\t const struct rte_flow_ops **ops)\n-{\n-\t*ops = &pmd_flow_ops;\n-\treturn 0;\n-}\n-\n static int\n pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)\n {\n@@ -240,7 +232,6 @@ static const struct eth_dev_ops pmd_ops = {\n \t.dev_infos_get = pmd_dev_infos_get,\n \t.rx_queue_setup = pmd_rx_queue_setup,\n \t.tx_queue_setup = pmd_tx_queue_setup,\n-\t.flow_ops_get = pmd_flow_ops_get,\n \t.mtr_ops_get = pmd_mtr_ops_get,\n };\n \ndiff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c\nindex 7556e50831..671f96cf77 100644\n--- a/drivers/net/softnic/rte_eth_softnic_cli.c\n+++ b/drivers/net/softnic/rte_eth_softnic_cli.c\n@@ -4731,81 +4731,6 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,\n \t}\n }\n \n-/**\n- * flowapi map\n- *  group <group_id>\n- *  ingress | egress\n- *  pipeline <pipeline_name>\n- *  table <table_id>\n- */\n-static void\n-cmd_softnic_flowapi_map(struct pmd_internals *softnic,\n-\t\tchar **tokens,\n-\t\tuint32_t n_tokens,\n-\t\tchar *out,\n-\t\tsize_t out_size)\n-{\n-\tchar *pipeline_name;\n-\tuint32_t group_id, table_id;\n-\tint ingress, status;\n-\n-\tif (n_tokens != 9) {\n-\t\tsnprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);\n-\t\treturn;\n-\t}\n-\n-\tif (strcmp(tokens[1], \"map\") != 0) {\n-\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"map\");\n-\t\treturn;\n-\t}\n-\n-\tif (strcmp(tokens[2], \"group\") != 0) {\n-\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"group\");\n-\t\treturn;\n-\t}\n-\n-\tif (softnic_parser_read_uint32(&group_id, tokens[3]) != 0) {\n-\t\tsnprintf(out, out_size, MSG_ARG_INVALID, \"group_id\");\n-\t\treturn;\n-\t}\n-\n-\tif (strcmp(tokens[4], \"ingress\") == 0) {\n-\t\tingress = 1;\n-\t} else if (strcmp(tokens[4], \"egress\") == 0) {\n-\t\tingress = 0;\n-\t} else {\n-\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"ingress | egress\");\n-\t\treturn;\n-\t}\n-\n-\tif (strcmp(tokens[5], \"pipeline\") != 0) {\n-\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"pipeline\");\n-\t\treturn;\n-\t}\n-\n-\tpipeline_name = tokens[6];\n-\n-\tif (strcmp(tokens[7], \"table\") != 0) {\n-\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"table\");\n-\t\treturn;\n-\t}\n-\n-\tif (softnic_parser_read_uint32(&table_id, tokens[8]) != 0) {\n-\t\tsnprintf(out, out_size, MSG_ARG_INVALID, \"table_id\");\n-\t\treturn;\n-\t}\n-\n-\tstatus = flow_attr_map_set(softnic,\n-\t\t\tgroup_id,\n-\t\t\tingress,\n-\t\t\tpipeline_name,\n-\t\t\ttable_id);\n-\tif (status) {\n-\t\tsnprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);\n-\t\treturn;\n-\t}\n-}\n-\n void\n softnic_cli_process(char *in, char *out, size_t out_size, void *arg)\n {\n@@ -5063,12 +4988,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)\n \t\t}\n \t}\n \n-\tif (strcmp(tokens[0], \"flowapi\") == 0) {\n-\t\tcmd_softnic_flowapi_map(softnic, tokens, n_tokens, out,\n-\t\t\t\t\tout_size);\n-\t\treturn;\n-\t}\n-\n \tsnprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);\n }\n \ndiff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c\ndeleted file mode 100644\nindex ad96288e7e..0000000000\n--- a/drivers/net/softnic/rte_eth_softnic_flow.c\n+++ /dev/null\n@@ -1,2293 +0,0 @@\n-/* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright(c) 2018 Intel Corporation\n- */\n-#include <stdint.h>\n-#include <stdlib.h>\n-#include <string.h>\n-\n-#include <rte_common.h>\n-#include <rte_byteorder.h>\n-#include <rte_malloc.h>\n-#include <rte_string_fns.h>\n-#include <rte_flow.h>\n-#include <rte_flow_driver.h>\n-#include <rte_tailq.h>\n-\n-#include \"rte_eth_softnic_internals.h\"\n-#include \"rte_eth_softnic.h\"\n-\n-#define rte_htons rte_cpu_to_be_16\n-#define rte_htonl rte_cpu_to_be_32\n-\n-#define rte_ntohs rte_be_to_cpu_16\n-#define rte_ntohl rte_be_to_cpu_32\n-\n-static struct rte_flow *\n-softnic_flow_find(struct softnic_table *table,\n-\tstruct softnic_table_rule_match *rule_match)\n-{\n-\tstruct rte_flow *flow;\n-\n-\tTAILQ_FOREACH(flow, &table->flows, node)\n-\t\tif (memcmp(&flow->match, rule_match, sizeof(*rule_match)) == 0)\n-\t\t\treturn flow;\n-\n-\treturn NULL;\n-}\n-\n-int\n-flow_attr_map_set(struct pmd_internals *softnic,\n-\t\tuint32_t group_id,\n-\t\tint ingress,\n-\t\tconst char *pipeline_name,\n-\t\tuint32_t table_id)\n-{\n-\tstruct pipeline *pipeline;\n-\tstruct flow_attr_map *map;\n-\n-\tif (group_id >= SOFTNIC_FLOW_MAX_GROUPS ||\n-\t\t\tpipeline_name == NULL)\n-\t\treturn -1;\n-\n-\tpipeline = softnic_pipeline_find(softnic, pipeline_name);\n-\tif (pipeline == NULL ||\n-\t\t\ttable_id >= pipeline->n_tables)\n-\t\treturn -1;\n-\n-\tmap = (ingress) ? &softnic->flow.ingress_map[group_id] :\n-\t\t&softnic->flow.egress_map[group_id];\n-\tstrlcpy(map->pipeline_name, pipeline_name, sizeof(map->pipeline_name));\n-\tmap->table_id = table_id;\n-\tmap->valid = 1;\n-\n-\treturn 0;\n-}\n-\n-struct flow_attr_map *\n-flow_attr_map_get(struct pmd_internals *softnic,\n-\t\tuint32_t group_id,\n-\t\tint ingress)\n-{\n-\tif (group_id >= SOFTNIC_FLOW_MAX_GROUPS)\n-\t\treturn NULL;\n-\n-\treturn (ingress) ? &softnic->flow.ingress_map[group_id] :\n-\t\t&softnic->flow.egress_map[group_id];\n-}\n-\n-static int\n-flow_pipeline_table_get(struct pmd_internals *softnic,\n-\t\tconst struct rte_flow_attr *attr,\n-\t\tconst char **pipeline_name,\n-\t\tuint32_t *table_id,\n-\t\tstruct rte_flow_error *error)\n-{\n-\tstruct flow_attr_map *map;\n-\n-\tif (attr == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ATTR,\n-\t\t\t\tNULL,\n-\t\t\t\t\"Null attr\");\n-\n-\tif (!attr->ingress && !attr->egress)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ATTR_INGRESS,\n-\t\t\t\tattr,\n-\t\t\t\t\"Ingress/egress not specified\");\n-\n-\tif (attr->ingress && attr->egress)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ATTR_INGRESS,\n-\t\t\t\tattr,\n-\t\t\t\t\"Setting both ingress and egress is not allowed\");\n-\n-\tmap = flow_attr_map_get(softnic,\n-\t\t\tattr->group,\n-\t\t\tattr->ingress);\n-\tif (map == NULL ||\n-\t\t\tmap->valid == 0)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ATTR_GROUP,\n-\t\t\t\tattr,\n-\t\t\t\t\"Invalid group ID\");\n-\n-\tif (pipeline_name)\n-\t\t*pipeline_name = map->pipeline_name;\n-\n-\tif (table_id)\n-\t\t*table_id = map->table_id;\n-\n-\treturn 0;\n-}\n-\n-union flow_item {\n-\tuint8_t raw[TABLE_RULE_MATCH_SIZE_MAX];\n-\tstruct rte_flow_item_eth eth;\n-\tstruct rte_flow_item_vlan vlan;\n-\tstruct rte_flow_item_ipv4 ipv4;\n-\tstruct rte_flow_item_ipv6 ipv6;\n-\tstruct rte_flow_item_icmp icmp;\n-\tstruct rte_flow_item_udp udp;\n-\tstruct rte_flow_item_tcp tcp;\n-\tstruct rte_flow_item_sctp sctp;\n-\tstruct rte_flow_item_vxlan vxlan;\n-\tstruct rte_flow_item_e_tag e_tag;\n-\tstruct rte_flow_item_nvgre nvgre;\n-\tstruct rte_flow_item_mpls mpls;\n-\tstruct rte_flow_item_gre gre;\n-\tstruct rte_flow_item_gtp gtp;\n-\tstruct rte_flow_item_esp esp;\n-\tstruct rte_flow_item_geneve geneve;\n-\tstruct rte_flow_item_vxlan_gpe vxlan_gpe;\n-\tstruct rte_flow_item_arp_eth_ipv4 arp_eth_ipv4;\n-\tstruct rte_flow_item_ipv6_ext ipv6_ext;\n-\tstruct rte_flow_item_icmp6 icmp6;\n-\tstruct rte_flow_item_icmp6_nd_ns icmp6_nd_ns;\n-\tstruct rte_flow_item_icmp6_nd_na icmp6_nd_na;\n-\tstruct rte_flow_item_icmp6_nd_opt icmp6_nd_opt;\n-\tstruct rte_flow_item_icmp6_nd_opt_sla_eth icmp6_nd_opt_sla_eth;\n-\tstruct rte_flow_item_icmp6_nd_opt_tla_eth icmp6_nd_opt_tla_eth;\n-};\n-\n-static const union flow_item flow_item_raw_mask;\n-\n-static int\n-flow_item_is_proto(enum rte_flow_item_type type,\n-\tconst void **mask,\n-\tsize_t *size)\n-{\n-\tswitch (type) {\n-\tcase RTE_FLOW_ITEM_TYPE_RAW:\n-\t\t*mask = &flow_item_raw_mask;\n-\t\t*size = sizeof(flow_item_raw_mask);\n-\t\treturn 1; /* TRUE */\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t*mask = &rte_flow_item_eth_mask;\n-\t\t*size = sizeof(struct rte_ether_hdr);\n-\t\treturn 1; /* TRUE */\n-\n-\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n-\t\t*mask = &rte_flow_item_vlan_mask;\n-\t\t*size = sizeof(struct rte_vlan_hdr);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n-\t\t*mask = &rte_flow_item_ipv4_mask;\n-\t\t*size = sizeof(struct rte_ipv4_hdr);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n-\t\t*mask = &rte_flow_item_ipv6_mask;\n-\t\t*size = sizeof(struct rte_ipv6_hdr);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ICMP:\n-\t\t*mask = &rte_flow_item_icmp_mask;\n-\t\t*size = sizeof(struct rte_flow_item_icmp);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_UDP:\n-\t\t*mask = &rte_flow_item_udp_mask;\n-\t\t*size = sizeof(struct rte_flow_item_udp);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_TCP:\n-\t\t*mask = &rte_flow_item_tcp_mask;\n-\t\t*size = sizeof(struct rte_flow_item_tcp);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_SCTP:\n-\t\t*mask = &rte_flow_item_sctp_mask;\n-\t\t*size = sizeof(struct rte_flow_item_sctp);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n-\t\t*mask = &rte_flow_item_vxlan_mask;\n-\t\t*size = sizeof(struct rte_flow_item_vxlan);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_E_TAG:\n-\t\t*mask = &rte_flow_item_e_tag_mask;\n-\t\t*size = sizeof(struct rte_flow_item_e_tag);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_NVGRE:\n-\t\t*mask = &rte_flow_item_nvgre_mask;\n-\t\t*size = sizeof(struct rte_flow_item_nvgre);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_MPLS:\n-\t\t*mask = &rte_flow_item_mpls_mask;\n-\t\t*size = sizeof(struct rte_flow_item_mpls);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_GRE:\n-\t\t*mask = &rte_flow_item_gre_mask;\n-\t\t*size = sizeof(struct rte_flow_item_gre);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_GTP:\n-\tcase RTE_FLOW_ITEM_TYPE_GTPC:\n-\tcase RTE_FLOW_ITEM_TYPE_GTPU:\n-\t\t*mask = &rte_flow_item_gtp_mask;\n-\t\t*size = sizeof(struct rte_flow_item_gtp);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ESP:\n-\t\t*mask = &rte_flow_item_esp_mask;\n-\t\t*size = sizeof(struct rte_flow_item_esp);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_GENEVE:\n-\t\t*mask = &rte_flow_item_geneve_mask;\n-\t\t*size = sizeof(struct rte_flow_item_geneve);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_VXLAN_GPE:\n-\t\t*mask = &rte_flow_item_vxlan_gpe_mask;\n-\t\t*size = sizeof(struct rte_flow_item_vxlan_gpe);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4:\n-\t\t*mask = &rte_flow_item_arp_eth_ipv4_mask;\n-\t\t*size = sizeof(struct rte_flow_item_arp_eth_ipv4);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_IPV6_EXT:\n-\t\t*mask = &rte_flow_item_ipv6_ext_mask;\n-\t\t*size = sizeof(struct rte_flow_item_ipv6_ext);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ICMP6:\n-\t\t*mask = &rte_flow_item_icmp6_mask;\n-\t\t*size = sizeof(struct rte_flow_item_icmp6);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS:\n-\t\t*mask = &rte_flow_item_icmp6_nd_ns_mask;\n-\t\t*size = sizeof(struct rte_flow_item_icmp6_nd_ns);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA:\n-\t\t*mask = &rte_flow_item_icmp6_nd_na_mask;\n-\t\t*size = sizeof(struct rte_flow_item_icmp6_nd_na);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT:\n-\t\t*mask = &rte_flow_item_icmp6_nd_opt_mask;\n-\t\t*size = sizeof(struct rte_flow_item_icmp6_nd_opt);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH:\n-\t\t*mask = &rte_flow_item_icmp6_nd_opt_sla_eth_mask;\n-\t\t*size = sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth);\n-\t\treturn 1;\n-\n-\tcase RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH:\n-\t\t*mask = &rte_flow_item_icmp6_nd_opt_tla_eth_mask;\n-\t\t*size = sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth);\n-\t\treturn 1;\n-\n-\tdefault: return 0; /* FALSE */\n-\t}\n-}\n-\n-static int\n-flow_item_raw_preprocess(const struct rte_flow_item *item,\n-\tunion flow_item *item_spec,\n-\tunion flow_item *item_mask,\n-\tsize_t *item_size,\n-\tint *item_disabled,\n-\tstruct rte_flow_error *error)\n-{\n-\tconst struct rte_flow_item_raw *item_raw_spec = item->spec;\n-\tconst struct rte_flow_item_raw *item_raw_mask = item->mask;\n-\tconst uint8_t *pattern;\n-\tconst uint8_t *pattern_mask;\n-\tuint8_t *spec = (uint8_t *)item_spec;\n-\tuint8_t *mask = (uint8_t *)item_mask;\n-\tsize_t pattern_length, pattern_offset, i;\n-\tint disabled;\n-\n-\tif (!item->spec)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"RAW: Null specification\");\n-\n-\tif (item->last)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"RAW: Range not allowed (last must be NULL)\");\n-\n-\tif (item_raw_spec->relative == 0)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"RAW: Absolute offset not supported\");\n-\n-\tif (item_raw_spec->search)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"RAW: Search not supported\");\n-\n-\tif (item_raw_spec->offset < 0)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"RAW: Negative offset not supported\");\n-\n-\tif (item_raw_spec->length == 0)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"RAW: Zero pattern length\");\n-\n-\tif (item_raw_spec->offset + item_raw_spec->length >\n-\t\tTABLE_RULE_MATCH_SIZE_MAX)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"RAW: Item too big\");\n-\n-\tif (!item_raw_spec->pattern && item_raw_mask && item_raw_mask->pattern)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"RAW: Non-NULL pattern mask not allowed with NULL pattern\");\n-\n-\tpattern = item_raw_spec->pattern;\n-\tpattern_mask = (item_raw_mask) ? item_raw_mask->pattern : NULL;\n-\tpattern_length = (size_t)item_raw_spec->length;\n-\tpattern_offset = (size_t)item_raw_spec->offset;\n-\n-\tdisabled = 0;\n-\tif (pattern_mask == NULL)\n-\t\tdisabled = 1;\n-\telse\n-\t\tfor (i = 0; i < pattern_length; i++)\n-\t\t\tif ((pattern)[i])\n-\t\t\t\tdisabled = 1;\n-\n-\tmemset(spec, 0, TABLE_RULE_MATCH_SIZE_MAX);\n-\tif (pattern)\n-\t\tmemcpy(&spec[pattern_offset], pattern, pattern_length);\n-\n-\tmemset(mask, 0, TABLE_RULE_MATCH_SIZE_MAX);\n-\tif (pattern_mask)\n-\t\tmemcpy(&mask[pattern_offset], pattern_mask, pattern_length);\n-\n-\t*item_size = pattern_offset + pattern_length;\n-\t*item_disabled = disabled;\n-\n-\treturn 0;\n-}\n-\n-static int\n-flow_item_proto_preprocess(const struct rte_flow_item *item,\n-\tunion flow_item *item_spec,\n-\tunion flow_item *item_mask,\n-\tsize_t *item_size,\n-\tint *item_disabled,\n-\tstruct rte_flow_error *error)\n-{\n-\tconst void *mask_default;\n-\tuint8_t *spec = (uint8_t *)item_spec;\n-\tuint8_t *mask = (uint8_t *)item_mask;\n-\tsize_t size, i;\n-\n-\tif (!flow_item_is_proto(item->type, &mask_default, &size))\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"Item type not supported\");\n-\n-\tif (item->type == RTE_FLOW_ITEM_TYPE_RAW)\n-\t\treturn flow_item_raw_preprocess(item,\n-\t\t\titem_spec,\n-\t\t\titem_mask,\n-\t\t\titem_size,\n-\t\t\titem_disabled,\n-\t\t\terror);\n-\n-\t/* spec */\n-\tif (!item->spec) {\n-\t\t/* If spec is NULL, then last and mask also have to be NULL. */\n-\t\tif (item->last || item->mask)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"Invalid item (NULL spec with non-NULL last or mask)\");\n-\n-\t\tmemset(item_spec, 0, size);\n-\t\tmemset(item_mask, 0, size);\n-\t\t*item_size = size;\n-\t\t*item_disabled = 1; /* TRUE */\n-\t\treturn 0;\n-\t}\n-\n-\tmemcpy(spec, item->spec, size);\n-\t*item_size = size;\n-\n-\t/* mask */\n-\tif (item->mask)\n-\t\tmemcpy(mask, item->mask, size);\n-\telse\n-\t\tmemcpy(mask, mask_default, size);\n-\n-\t/* disabled */\n-\tfor (i = 0; i < size; i++)\n-\t\tif (mask[i])\n-\t\t\tbreak;\n-\t*item_disabled = (i == size) ? 1 : 0;\n-\n-\t/* Apply mask over spec. */\n-\tfor (i = 0; i < size; i++)\n-\t\tspec[i] &= mask[i];\n-\n-\t/* last */\n-\tif (item->last) {\n-\t\tuint8_t last[size];\n-\n-\t\t/* init last */\n-\t\tmemcpy(last, item->last, size);\n-\t\tfor (i = 0; i < size; i++)\n-\t\t\tlast[i] &= mask[i];\n-\n-\t\t/* check for range */\n-\t\tfor (i = 0; i < size; i++)\n-\t\t\tif (last[i] != spec[i])\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\titem,\n-\t\t\t\t\t\"Range not supported\");\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/***\n- * Skip disabled protocol items and VOID items\n- * until any of the mutually exclusive conditions\n- * from the list below takes place:\n- *    (A) A protocol present in the proto_mask\n- *        is met (either ENABLED or DISABLED);\n- *    (B) A protocol NOT present in the proto_mask is met in ENABLED state;\n- *    (C) The END item is met.\n- */\n-static int\n-flow_item_skip_disabled_protos(const struct rte_flow_item **item,\n-\tuint64_t proto_mask,\n-\tsize_t *length,\n-\tstruct rte_flow_error *error)\n-{\n-\tsize_t len = 0;\n-\n-\tfor ( ; (*item)->type != RTE_FLOW_ITEM_TYPE_END; (*item)++) {\n-\t\tunion flow_item spec, mask;\n-\t\tsize_t size;\n-\t\tint disabled = 0, status;\n-\n-\t\tif ((*item)->type == RTE_FLOW_ITEM_TYPE_VOID)\n-\t\t\tcontinue;\n-\n-\t\tstatus = flow_item_proto_preprocess(*item,\n-\t\t\t\t&spec,\n-\t\t\t\t&mask,\n-\t\t\t\t&size,\n-\t\t\t\t&disabled,\n-\t\t\t\terror);\n-\t\tif (status)\n-\t\t\treturn status;\n-\n-\t\tif ((proto_mask & (1LLU << (*item)->type)) ||\n-\t\t\t\t!disabled)\n-\t\t\tbreak;\n-\n-\t\tlen += size;\n-\t}\n-\n-\tif (length)\n-\t\t*length = len;\n-\n-\treturn 0;\n-}\n-\n-#define FLOW_ITEM_PROTO_IP \\\n-\t((1LLU << RTE_FLOW_ITEM_TYPE_IPV4) | \\\n-\t (1LLU << RTE_FLOW_ITEM_TYPE_IPV6))\n-\n-static void\n-flow_item_skip_void(const struct rte_flow_item **item)\n-{\n-\tfor ( ; ; (*item)++)\n-\t\tif ((*item)->type != RTE_FLOW_ITEM_TYPE_VOID)\n-\t\t\treturn;\n-}\n-\n-#define IP_PROTOCOL_TCP 0x06\n-#define IP_PROTOCOL_UDP 0x11\n-#define IP_PROTOCOL_SCTP 0x84\n-\n-static int\n-mask_to_depth(uint64_t mask,\n-\t\tuint32_t *depth)\n-{\n-\tuint64_t n;\n-\n-\tif (mask == UINT64_MAX) {\n-\t\tif (depth)\n-\t\t\t*depth = 64;\n-\n-\t\treturn 0;\n-\t}\n-\n-\tmask = ~mask;\n-\n-\tif (mask & (mask + 1))\n-\t\treturn -1;\n-\n-\tn = __builtin_popcountll(mask);\n-\tif (depth)\n-\t\t*depth = (uint32_t)(64 - n);\n-\n-\treturn 0;\n-}\n-\n-static int\n-ipv4_mask_to_depth(uint32_t mask,\n-\t\tuint32_t *depth)\n-{\n-\tuint32_t d;\n-\tint status;\n-\n-\tstatus = mask_to_depth(mask | (UINT64_MAX << 32), &d);\n-\tif (status)\n-\t\treturn status;\n-\n-\td -= 32;\n-\tif (depth)\n-\t\t*depth = d;\n-\n-\treturn 0;\n-}\n-\n-static int\n-ipv6_mask_to_depth(uint8_t *mask,\n-\tuint32_t *depth)\n-{\n-\tuint64_t *m = (uint64_t *)mask;\n-\tuint64_t m0 = rte_be_to_cpu_64(m[0]);\n-\tuint64_t m1 = rte_be_to_cpu_64(m[1]);\n-\tuint32_t d0, d1;\n-\tint status;\n-\n-\tstatus = mask_to_depth(m0, &d0);\n-\tif (status)\n-\t\treturn status;\n-\n-\tstatus = mask_to_depth(m1, &d1);\n-\tif (status)\n-\t\treturn status;\n-\n-\tif (d0 < 64 && d1)\n-\t\treturn -1;\n-\n-\tif (depth)\n-\t\t*depth = d0 + d1;\n-\n-\treturn 0;\n-}\n-\n-static int\n-port_mask_to_range(uint16_t port,\n-\tuint16_t port_mask,\n-\tuint16_t *port0,\n-\tuint16_t *port1)\n-{\n-\tint status;\n-\tuint16_t p0, p1;\n-\n-\tstatus = mask_to_depth(port_mask | (UINT64_MAX << 16), NULL);\n-\tif (status)\n-\t\treturn -1;\n-\n-\tp0 = port & port_mask;\n-\tp1 = p0 | ~port_mask;\n-\n-\tif (port0)\n-\t\t*port0 = p0;\n-\n-\tif (port1)\n-\t\t*port1 = p1;\n-\n-\treturn 0;\n-}\n-\n-static int\n-flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,\n-\t\tstruct pipeline *pipeline __rte_unused,\n-\t\tstruct softnic_table *table __rte_unused,\n-\t\tconst struct rte_flow_attr *attr,\n-\t\tconst struct rte_flow_item *item,\n-\t\tstruct softnic_table_rule_match *rule_match,\n-\t\tstruct rte_flow_error *error)\n-{\n-\tunion flow_item spec, mask;\n-\tsize_t size, length = 0;\n-\tint disabled = 0, status;\n-\tuint8_t ip_proto, ip_proto_mask;\n-\n-\tmemset(rule_match, 0, sizeof(*rule_match));\n-\trule_match->match_type = TABLE_ACL;\n-\trule_match->match.acl.priority = attr->priority;\n-\n-\t/* VOID or disabled protos only, if any. */\n-\tstatus = flow_item_skip_disabled_protos(&item,\n-\t\t\tFLOW_ITEM_PROTO_IP, &length, error);\n-\tif (status)\n-\t\treturn status;\n-\n-\t/* IP only. */\n-\tstatus = flow_item_proto_preprocess(item, &spec, &mask,\n-\t\t\t&size, &disabled, error);\n-\tif (status)\n-\t\treturn status;\n-\n-\tswitch (item->type) {\n-\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n-\t{\n-\t\tuint32_t sa_depth, da_depth;\n-\n-\t\tstatus = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.src_addr),\n-\t\t\t\t&sa_depth);\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal IPv4 header source address mask\");\n-\n-\t\tstatus = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.dst_addr),\n-\t\t\t\t&da_depth);\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal IPv4 header destination address mask\");\n-\n-\t\tip_proto = spec.ipv4.hdr.next_proto_id;\n-\t\tip_proto_mask = mask.ipv4.hdr.next_proto_id;\n-\n-\t\trule_match->match.acl.ip_version = 1;\n-\t\trule_match->match.acl.ipv4.sa =\n-\t\t\trte_ntohl(spec.ipv4.hdr.src_addr);\n-\t\trule_match->match.acl.ipv4.da =\n-\t\t\trte_ntohl(spec.ipv4.hdr.dst_addr);\n-\t\trule_match->match.acl.sa_depth = sa_depth;\n-\t\trule_match->match.acl.da_depth = da_depth;\n-\t\trule_match->match.acl.proto = ip_proto;\n-\t\trule_match->match.acl.proto_mask = ip_proto_mask;\n-\t\tbreak;\n-\t} /* RTE_FLOW_ITEM_TYPE_IPV4 */\n-\n-\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n-\t{\n-\t\tuint32_t sa_depth, da_depth;\n-\n-\t\tstatus = ipv6_mask_to_depth(mask.ipv6.hdr.src_addr, &sa_depth);\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal IPv6 header source address mask\");\n-\n-\t\tstatus = ipv6_mask_to_depth(mask.ipv6.hdr.dst_addr, &da_depth);\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal IPv6 header destination address mask\");\n-\n-\t\tip_proto = spec.ipv6.hdr.proto;\n-\t\tip_proto_mask = mask.ipv6.hdr.proto;\n-\n-\t\trule_match->match.acl.ip_version = 0;\n-\t\tmemcpy(rule_match->match.acl.ipv6.sa,\n-\t\t\tspec.ipv6.hdr.src_addr,\n-\t\t\tsizeof(spec.ipv6.hdr.src_addr));\n-\t\tmemcpy(rule_match->match.acl.ipv6.da,\n-\t\t\tspec.ipv6.hdr.dst_addr,\n-\t\t\tsizeof(spec.ipv6.hdr.dst_addr));\n-\t\trule_match->match.acl.sa_depth = sa_depth;\n-\t\trule_match->match.acl.da_depth = da_depth;\n-\t\trule_match->match.acl.proto = ip_proto;\n-\t\trule_match->match.acl.proto_mask = ip_proto_mask;\n-\t\tbreak;\n-\t} /* RTE_FLOW_ITEM_TYPE_IPV6 */\n-\n-\tdefault:\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"ACL: IP protocol required\");\n-\t} /* switch */\n-\n-\tif (ip_proto_mask != UINT8_MAX)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"ACL: Illegal IP protocol mask\");\n-\n-\titem++;\n-\n-\t/* VOID only, if any. */\n-\tflow_item_skip_void(&item);\n-\n-\t/* TCP/UDP/SCTP only. */\n-\tstatus = flow_item_proto_preprocess(item, &spec, &mask,\n-\t\t\t&size, &disabled, error);\n-\tif (status)\n-\t\treturn status;\n-\n-\tswitch (item->type) {\n-\tcase RTE_FLOW_ITEM_TYPE_TCP:\n-\t{\n-\t\tuint16_t sp0, sp1, dp0, dp1;\n-\n-\t\tif (ip_proto != IP_PROTOCOL_TCP)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Item type is TCP, but IP protocol is not\");\n-\n-\t\tstatus = port_mask_to_range(rte_ntohs(spec.tcp.hdr.src_port),\n-\t\t\t\trte_ntohs(mask.tcp.hdr.src_port),\n-\t\t\t\t&sp0,\n-\t\t\t\t&sp1);\n-\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal TCP source port mask\");\n-\n-\t\tstatus = port_mask_to_range(rte_ntohs(spec.tcp.hdr.dst_port),\n-\t\t\t\trte_ntohs(mask.tcp.hdr.dst_port),\n-\t\t\t\t&dp0,\n-\t\t\t\t&dp1);\n-\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal TCP destination port mask\");\n-\n-\t\trule_match->match.acl.sp0 = sp0;\n-\t\trule_match->match.acl.sp1 = sp1;\n-\t\trule_match->match.acl.dp0 = dp0;\n-\t\trule_match->match.acl.dp1 = dp1;\n-\n-\t\tbreak;\n-\t} /* RTE_FLOW_ITEM_TYPE_TCP */\n-\n-\tcase RTE_FLOW_ITEM_TYPE_UDP:\n-\t{\n-\t\tuint16_t sp0, sp1, dp0, dp1;\n-\n-\t\tif (ip_proto != IP_PROTOCOL_UDP)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Item type is UDP, but IP protocol is not\");\n-\n-\t\tstatus = port_mask_to_range(rte_ntohs(spec.udp.hdr.src_port),\n-\t\t\trte_ntohs(mask.udp.hdr.src_port),\n-\t\t\t&sp0,\n-\t\t\t&sp1);\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal UDP source port mask\");\n-\n-\t\tstatus = port_mask_to_range(rte_ntohs(spec.udp.hdr.dst_port),\n-\t\t\trte_ntohs(mask.udp.hdr.dst_port),\n-\t\t\t&dp0,\n-\t\t\t&dp1);\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal UDP destination port mask\");\n-\n-\t\trule_match->match.acl.sp0 = sp0;\n-\t\trule_match->match.acl.sp1 = sp1;\n-\t\trule_match->match.acl.dp0 = dp0;\n-\t\trule_match->match.acl.dp1 = dp1;\n-\n-\t\tbreak;\n-\t} /* RTE_FLOW_ITEM_TYPE_UDP */\n-\n-\tcase RTE_FLOW_ITEM_TYPE_SCTP:\n-\t{\n-\t\tuint16_t sp0, sp1, dp0, dp1;\n-\n-\t\tif (ip_proto != IP_PROTOCOL_SCTP)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Item type is SCTP, but IP protocol is not\");\n-\n-\t\tstatus = port_mask_to_range(rte_ntohs(spec.sctp.hdr.src_port),\n-\t\t\trte_ntohs(mask.sctp.hdr.src_port),\n-\t\t\t&sp0,\n-\t\t\t&sp1);\n-\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal SCTP source port mask\");\n-\n-\t\tstatus = port_mask_to_range(rte_ntohs(spec.sctp.hdr.dst_port),\n-\t\t\trte_ntohs(mask.sctp.hdr.dst_port),\n-\t\t\t&dp0,\n-\t\t\t&dp1);\n-\t\tif (status)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"ACL: Illegal SCTP destination port mask\");\n-\n-\t\trule_match->match.acl.sp0 = sp0;\n-\t\trule_match->match.acl.sp1 = sp1;\n-\t\trule_match->match.acl.dp0 = dp0;\n-\t\trule_match->match.acl.dp1 = dp1;\n-\n-\t\tbreak;\n-\t} /* RTE_FLOW_ITEM_TYPE_SCTP */\n-\n-\tdefault:\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"ACL: TCP/UDP/SCTP required\");\n-\t} /* switch */\n-\n-\titem++;\n-\n-\t/* VOID or disabled protos only, if any. */\n-\tstatus = flow_item_skip_disabled_protos(&item, 0, NULL, error);\n-\tif (status)\n-\t\treturn status;\n-\n-\t/* END only. */\n-\tif (item->type != RTE_FLOW_ITEM_TYPE_END)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"ACL: Expecting END item\");\n-\n-\treturn 0;\n-}\n-\n-/***\n- * Both *tmask* and *fmask* are byte arrays of size *tsize* and *fsize*\n- * respectively.\n- * They are located within a larger buffer at offsets *toffset* and *foffset*\n- * respectively. Both *tmask* and *fmask* represent bitmasks for the larger\n- * buffer.\n- * Question: are the two masks equivalent?\n- *\n- * Notes:\n- * 1. Offset basically indicates that the first offset bytes in the buffer\n- *    are \"don't care\", so offset is equivalent to pre-pending an \"all-zeros\"\n- *    array of *offset* bytes to the *mask*.\n- * 2. Each *mask* might contain a number of zero bytes at the beginning or\n- *    at the end.\n- * 3. Bytes in the larger buffer after the end of the *mask* are also considered\n- *    \"don't care\", so they are equivalent to appending an \"all-zeros\" array of\n- *    bytes to the *mask*.\n- *\n- * Example:\n- * Buffer = [xx xx xx xx xx xx xx xx], buffer size = 8 bytes\n- * tmask = [00 22 00 33 00], toffset = 2, tsize = 5\n- *    => buffer mask = [00 00 00 22 00 33 00 00]\n- * fmask = [22 00 33], foffset = 3, fsize = 3 =>\n- *    => buffer mask = [00 00 00 22 00 33 00 00]\n- * Therefore, the tmask and fmask from this example are equivalent.\n- */\n-static int\n-hash_key_mask_is_same(uint8_t *tmask,\n-\tsize_t toffset,\n-\tsize_t tsize,\n-\tuint8_t *fmask,\n-\tsize_t foffset,\n-\tsize_t fsize,\n-\tsize_t *toffset_plus,\n-\tsize_t *foffset_plus)\n-{\n-\tsize_t tpos; /* Position of first non-zero byte in the tmask buffer. */\n-\tsize_t fpos; /* Position of first non-zero byte in the fmask buffer. */\n-\n-\t/* Compute tpos and fpos. */\n-\tfor (tpos = 0; tmask[tpos] == 0; tpos++)\n-\t\t;\n-\tfor (fpos = 0; fmask[fpos] == 0; fpos++)\n-\t\t;\n-\n-\tif (toffset + tpos != foffset + fpos)\n-\t\treturn 0; /* FALSE */\n-\n-\ttsize -= tpos;\n-\tfsize -= fpos;\n-\n-\tif (tsize < fsize) {\n-\t\tsize_t i;\n-\n-\t\tfor (i = 0; i < tsize; i++)\n-\t\t\tif (tmask[tpos + i] != fmask[fpos + i])\n-\t\t\t\treturn 0; /* FALSE */\n-\n-\t\tfor ( ; i < fsize; i++)\n-\t\t\tif (fmask[fpos + i])\n-\t\t\t\treturn 0; /* FALSE */\n-\t} else {\n-\t\tsize_t i;\n-\n-\t\tfor (i = 0; i < fsize; i++)\n-\t\t\tif (tmask[tpos + i] != fmask[fpos + i])\n-\t\t\t\treturn 0; /* FALSE */\n-\n-\t\tfor ( ; i < tsize; i++)\n-\t\t\tif (tmask[tpos + i])\n-\t\t\t\treturn 0; /* FALSE */\n-\t}\n-\n-\tif (toffset_plus)\n-\t\t*toffset_plus = tpos;\n-\n-\tif (foffset_plus)\n-\t\t*foffset_plus = fpos;\n-\n-\treturn 1; /* TRUE */\n-}\n-\n-static int\n-flow_rule_match_hash_get(struct pmd_internals *softnic __rte_unused,\n-\tstruct pipeline *pipeline __rte_unused,\n-\tstruct softnic_table *table,\n-\tconst struct rte_flow_attr *attr __rte_unused,\n-\tconst struct rte_flow_item *item,\n-\tstruct softnic_table_rule_match *rule_match,\n-\tstruct rte_flow_error *error)\n-{\n-\tstruct softnic_table_rule_match_hash key, key_mask;\n-\tstruct softnic_table_hash_params *params = &table->params.match.hash;\n-\tsize_t offset = 0, length = 0, tpos, fpos;\n-\tint status;\n-\n-\tmemset(&key, 0, sizeof(key));\n-\tmemset(&key_mask, 0, sizeof(key_mask));\n-\n-\t/* VOID or disabled protos only, if any. */\n-\tstatus = flow_item_skip_disabled_protos(&item, 0, &offset, error);\n-\tif (status)\n-\t\treturn status;\n-\n-\tif (item->type == RTE_FLOW_ITEM_TYPE_END)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\titem,\n-\t\t\t\"HASH: END detected too early\");\n-\n-\t/* VOID or any protocols (enabled or disabled). */\n-\tfor ( ; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {\n-\t\tunion flow_item spec, mask;\n-\t\tsize_t size;\n-\t\tint disabled, status;\n-\n-\t\tif (item->type == RTE_FLOW_ITEM_TYPE_VOID)\n-\t\t\tcontinue;\n-\n-\t\tstatus = flow_item_proto_preprocess(item,\n-\t\t\t&spec,\n-\t\t\t&mask,\n-\t\t\t&size,\n-\t\t\t&disabled,\n-\t\t\terror);\n-\t\tif (status)\n-\t\t\treturn status;\n-\n-\t\tif (length + size > sizeof(key)) {\n-\t\t\tif (disabled)\n-\t\t\t\tbreak;\n-\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tENOTSUP,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"HASH: Item too big\");\n-\t\t}\n-\n-\t\tmemcpy(&key.key[length], &spec, size);\n-\t\tmemcpy(&key_mask.key[length], &mask, size);\n-\t\tlength += size;\n-\t}\n-\n-\tif (item->type != RTE_FLOW_ITEM_TYPE_END) {\n-\t\t/* VOID or disabled protos only, if any. */\n-\t\tstatus = flow_item_skip_disabled_protos(&item, 0, NULL, error);\n-\t\tif (status)\n-\t\t\treturn status;\n-\n-\t\t/* END only. */\n-\t\tif (item->type != RTE_FLOW_ITEM_TYPE_END)\n-\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\titem,\n-\t\t\t\t\"HASH: Expecting END item\");\n-\t}\n-\n-\t/* Compare flow key mask against table key mask. */\n-\toffset += sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;\n-\n-\tif (!hash_key_mask_is_same(params->key_mask,\n-\t\tparams->key_offset,\n-\t\tparams->key_size,\n-\t\tkey_mask.key,\n-\t\toffset,\n-\t\tlength,\n-\t\t&tpos,\n-\t\t&fpos))\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"HASH: Item list is not observing the match format\");\n-\n-\t/* Rule match. */\n-\tmemset(rule_match, 0, sizeof(*rule_match));\n-\trule_match->match_type = TABLE_HASH;\n-\tmemcpy(&rule_match->match.hash.key[tpos],\n-\t\t&key.key[fpos],\n-\t\tRTE_MIN(sizeof(rule_match->match.hash.key) - tpos,\n-\t\t\tlength - fpos));\n-\n-\treturn 0;\n-}\n-\n-static int\n-flow_rule_match_get(struct pmd_internals *softnic,\n-\t\tstruct pipeline *pipeline,\n-\t\tstruct softnic_table *table,\n-\t\tconst struct rte_flow_attr *attr,\n-\t\tconst struct rte_flow_item *item,\n-\t\tstruct softnic_table_rule_match *rule_match,\n-\t\tstruct rte_flow_error *error)\n-{\n-\tswitch (table->params.match_type) {\n-\tcase TABLE_ACL:\n-\t\treturn flow_rule_match_acl_get(softnic,\n-\t\t\tpipeline,\n-\t\t\ttable,\n-\t\t\tattr,\n-\t\t\titem,\n-\t\t\trule_match,\n-\t\t\terror);\n-\n-\t\t/* FALLTHROUGH */\n-\n-\tcase TABLE_HASH:\n-\t\treturn flow_rule_match_hash_get(softnic,\n-\t\t\tpipeline,\n-\t\t\ttable,\n-\t\t\tattr,\n-\t\t\titem,\n-\t\t\trule_match,\n-\t\t\terror);\n-\n-\t\t/* FALLTHROUGH */\n-\n-\tdefault:\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tENOTSUP,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"Unsupported pipeline table match type\");\n-\t}\n-}\n-\n-static int\n-flow_rule_action_get(struct pmd_internals *softnic,\n-\tstruct pipeline *pipeline,\n-\tstruct softnic_table *table,\n-\tconst struct rte_flow_attr *attr,\n-\tconst struct rte_flow_action *action,\n-\tstruct softnic_table_rule_action *rule_action,\n-\tstruct rte_flow_error *error)\n-{\n-\tstruct softnic_table_action_profile *profile;\n-\tstruct softnic_table_action_profile_params *params;\n-\tstruct softnic_mtr_meter_policy *policy;\n-\tint n_jump_queue_rss_drop = 0;\n-\tint n_count = 0;\n-\tint n_mark = 0;\n-\tint n_vxlan_decap = 0;\n-\n-\tprofile = softnic_table_action_profile_find(softnic,\n-\t\ttable->params.action_profile_name);\n-\tif (profile == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\taction,\n-\t\t\t\"JUMP: Table action profile\");\n-\n-\tparams = &profile->params;\n-\n-\tfor ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {\n-\t\tif (action->type == RTE_FLOW_ACTION_TYPE_VOID)\n-\t\t\tcontinue;\n-\n-\t\tswitch (action->type) {\n-\t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n-\t\t{\n-\t\t\tconst struct rte_flow_action_jump *conf = action->conf;\n-\t\t\tstruct flow_attr_map *map;\n-\n-\t\t\tif (conf == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"JUMP: Null configuration\");\n-\n-\t\t\tif (n_jump_queue_rss_drop)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"Only one termination action is\"\n-\t\t\t\t\t\" allowed per flow\");\n-\n-\t\t\tif ((params->action_mask &\n-\t\t\t\t(1LLU << RTE_TABLE_ACTION_FWD)) == 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"JUMP action not enabled for this table\");\n-\n-\t\t\tn_jump_queue_rss_drop = 1;\n-\n-\t\t\tmap = flow_attr_map_get(softnic,\n-\t\t\t\tconf->group,\n-\t\t\t\tattr->ingress);\n-\t\t\tif (map == NULL || map->valid == 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"JUMP: Invalid group mapping\");\n-\n-\t\t\tif (strcmp(pipeline->name, map->pipeline_name) != 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"JUMP: Jump to table in different pipeline\");\n-\n-\t\t\t/* RTE_TABLE_ACTION_FWD */\n-\t\t\trule_action->fwd.action = RTE_PIPELINE_ACTION_TABLE;\n-\t\t\trule_action->fwd.id = map->table_id;\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;\n-\t\t\tbreak;\n-\t\t} /* RTE_FLOW_ACTION_TYPE_JUMP */\n-\n-\t\tcase RTE_FLOW_ACTION_TYPE_QUEUE:\n-\t\t{\n-\t\t\tchar name[NAME_SIZE];\n-\t\t\tstruct rte_eth_dev *dev;\n-\t\t\tconst struct rte_flow_action_queue *conf = action->conf;\n-\t\t\tuint32_t port_id;\n-\t\t\tint status;\n-\n-\t\t\tif (conf == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"QUEUE: Null configuration\");\n-\n-\t\t\tif (n_jump_queue_rss_drop)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"Only one termination action is allowed\"\n-\t\t\t\t\t\" per flow\");\n-\n-\t\t\tif ((params->action_mask &\n-\t\t\t\t(1LLU << RTE_TABLE_ACTION_FWD)) == 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"QUEUE action not enabled for this table\");\n-\n-\t\t\tn_jump_queue_rss_drop = 1;\n-\n-\t\t\tdev = ETHDEV(softnic);\n-\t\t\tif (dev == NULL ||\n-\t\t\t\tconf->index >= dev->data->nb_rx_queues)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"QUEUE: Invalid RX queue ID\");\n-\n-\t\t\tsnprintf(name, sizeof(name), \"RXQ%u\",\n-\t\t\t\t\t(uint32_t)conf->index);\n-\n-\t\t\tstatus = softnic_pipeline_port_out_find(softnic,\n-\t\t\t\tpipeline->name,\n-\t\t\t\tname,\n-\t\t\t\t&port_id);\n-\t\t\tif (status)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"QUEUE: RX queue not accessible from this pipeline\");\n-\n-\t\t\t/* RTE_TABLE_ACTION_FWD */\n-\t\t\trule_action->fwd.action = RTE_PIPELINE_ACTION_PORT;\n-\t\t\trule_action->fwd.id = port_id;\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;\n-\t\t\tbreak;\n-\t\t} /*RTE_FLOW_ACTION_TYPE_QUEUE */\n-\n-\t\tcase RTE_FLOW_ACTION_TYPE_RSS:\n-\t\t{\n-\t\t\tconst struct rte_flow_action_rss *conf = action->conf;\n-\t\t\tuint32_t i;\n-\n-\t\t\tif (conf == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"RSS: Null configuration\");\n-\n-\t\t\tif (!rte_is_power_of_2(conf->queue_num))\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\tconf,\n-\t\t\t\t\t\"RSS: Number of queues must be a power of 2\");\n-\n-\t\t\tif (conf->queue_num > RTE_DIM(rule_action->lb.out))\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\tconf,\n-\t\t\t\t\t\"RSS: Number of queues too big\");\n-\n-\t\t\tif (n_jump_queue_rss_drop)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"Only one termination action is allowed per flow\");\n-\n-\t\t\tif (((params->action_mask &\n-\t\t\t\t(1LLU << RTE_TABLE_ACTION_FWD)) == 0) ||\n-\t\t\t\t((params->action_mask &\n-\t\t\t\t(1LLU << RTE_TABLE_ACTION_LB)) == 0))\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"RSS action not supported by this table\");\n-\n-\t\t\tif (params->lb.out_offset !=\n-\t\t\t\tpipeline->params.offset_port_id)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"RSS action not supported by this pipeline\");\n-\n-\t\t\tn_jump_queue_rss_drop = 1;\n-\n-\t\t\t/* RTE_TABLE_ACTION_LB */\n-\t\t\tfor (i = 0; i < conf->queue_num; i++) {\n-\t\t\t\tchar name[NAME_SIZE];\n-\t\t\t\tstruct rte_eth_dev *dev;\n-\t\t\t\tuint32_t port_id;\n-\t\t\t\tint status;\n-\n-\t\t\t\tdev = ETHDEV(softnic);\n-\t\t\t\tif (dev == NULL ||\n-\t\t\t\t\tconf->queue[i] >=\n-\t\t\t\t\t\tdev->data->nb_rx_queues)\n-\t\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\t\tEINVAL,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\taction,\n-\t\t\t\t\t\t\"RSS: Invalid RX queue ID\");\n-\n-\t\t\t\tsnprintf(name, sizeof(name), \"RXQ%u\",\n-\t\t\t\t\t(uint32_t)conf->queue[i]);\n-\n-\t\t\t\tstatus = softnic_pipeline_port_out_find(softnic,\n-\t\t\t\t\tpipeline->name,\n-\t\t\t\t\tname,\n-\t\t\t\t\t&port_id);\n-\t\t\t\tif (status)\n-\t\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\t\tENOTSUP,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\taction,\n-\t\t\t\t\t\t\"RSS: RX queue not accessible from this pipeline\");\n-\n-\t\t\t\trule_action->lb.out[i] = port_id;\n-\t\t\t}\n-\n-\t\t\tfor ( ; i < RTE_DIM(rule_action->lb.out); i++)\n-\t\t\t\trule_action->lb.out[i] =\n-\t\t\t\trule_action->lb.out[i % conf->queue_num];\n-\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_LB;\n-\n-\t\t\t/* RTE_TABLE_ACTION_FWD */\n-\t\t\trule_action->fwd.action = RTE_PIPELINE_ACTION_PORT_META;\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;\n-\t\t\tbreak;\n-\t\t} /* RTE_FLOW_ACTION_TYPE_RSS */\n-\n-\t\tcase RTE_FLOW_ACTION_TYPE_DROP:\n-\t\t{\n-\t\t\tconst void *conf = action->conf;\n-\n-\t\t\tif (conf != NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"DROP: No configuration required\");\n-\n-\t\t\tif (n_jump_queue_rss_drop)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"Only one termination action is allowed per flow\");\n-\t\t\tif ((params->action_mask &\n-\t\t\t\t(1LLU << RTE_TABLE_ACTION_FWD)) == 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"DROP action not supported by this table\");\n-\n-\t\t\tn_jump_queue_rss_drop = 1;\n-\n-\t\t\t/* RTE_TABLE_ACTION_FWD */\n-\t\t\trule_action->fwd.action = RTE_PIPELINE_ACTION_DROP;\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;\n-\t\t\tbreak;\n-\t\t} /* RTE_FLOW_ACTION_TYPE_DROP */\n-\n-\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n-\t\t{\n-\t\t\tconst struct rte_flow_action_count *conf = action->conf;\n-\n-\t\t\tif (conf == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"COUNT: Null configuration\");\n-\n-\t\t\tif (n_count)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"Only one COUNT action per flow\");\n-\n-\t\t\tif ((params->action_mask &\n-\t\t\t\t(1LLU << RTE_TABLE_ACTION_STATS)) == 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"COUNT action not supported by this table\");\n-\n-\t\t\tn_count = 1;\n-\n-\t\t\t/* RTE_TABLE_ACTION_STATS */\n-\t\t\trule_action->stats.n_packets = 0;\n-\t\t\trule_action->stats.n_bytes = 0;\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_STATS;\n-\t\t\tbreak;\n-\t\t} /* RTE_FLOW_ACTION_TYPE_COUNT */\n-\n-\t\tcase RTE_FLOW_ACTION_TYPE_MARK:\n-\t\t{\n-\t\t\tconst struct rte_flow_action_mark *conf = action->conf;\n-\n-\t\t\tif (conf == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"MARK: Null configuration\");\n-\n-\t\t\tif (n_mark)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"Only one MARK action per flow\");\n-\n-\t\t\tif ((params->action_mask &\n-\t\t\t\t(1LLU << RTE_TABLE_ACTION_TAG)) == 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"MARK action not supported by this table\");\n-\n-\t\t\tn_mark = 1;\n-\n-\t\t\t/* RTE_TABLE_ACTION_TAG */\n-\t\t\trule_action->tag.tag = conf->id;\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_TAG;\n-\t\t\tbreak;\n-\t\t} /* RTE_FLOW_ACTION_TYPE_MARK */\n-\n-\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n-\t\t{\n-\t\t\tconst struct rte_flow_action_mark *conf = action->conf;\n-\n-\t\t\tif (conf)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"VXLAN DECAP: Non-null configuration\");\n-\n-\t\t\tif (n_vxlan_decap)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"Only one VXLAN DECAP action per flow\");\n-\n-\t\t\tif ((params->action_mask &\n-\t\t\t\t(1LLU << RTE_TABLE_ACTION_DECAP)) == 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tENOTSUP,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"VXLAN DECAP action not supported by this table\");\n-\n-\t\t\tn_vxlan_decap = 1;\n-\n-\t\t\t/* RTE_TABLE_ACTION_DECAP */\n-\t\t\trule_action->decap.n = 50; /* Ether/IPv4/UDP/VXLAN */\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;\n-\t\t\tbreak;\n-\t\t} /* RTE_FLOW_ACTION_TYPE_VXLAN_DECAP */\n-\n-\t\tcase RTE_FLOW_ACTION_TYPE_METER:\n-\t\t{\n-\t\t\tconst struct rte_flow_action_meter *conf = action->conf;\n-\t\t\tstruct softnic_mtr_meter_profile *mp;\n-\t\t\tstruct softnic_mtr *m;\n-\t\t\tuint32_t table_id = table - pipeline->table;\n-\t\t\tuint32_t meter_profile_id;\n-\t\t\tint status;\n-\n-\t\t\tif ((params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"METER: Table action not supported\");\n-\n-\t\t\tif (params->mtr.n_tc != 1)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"METER: Multiple TCs not supported\");\n-\n-\t\t\tif (conf == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"METER: Null configuration\");\n-\n-\t\t\tm = softnic_mtr_find(softnic, conf->mtr_id);\n-\n-\t\t\tif (m == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"METER: Invalid meter ID\");\n-\n-\t\t\tif (m->flow)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"METER: Meter already attached to a flow\");\n-\n-\t\t\tmeter_profile_id = m->params.meter_profile_id;\n-\t\t\tmp = softnic_mtr_meter_profile_find(softnic, meter_profile_id);\n-\n-\t\t\t/* Add meter profile to pipeline table */\n-\t\t\tif (!softnic_pipeline_table_meter_profile_find(table,\n-\t\t\t\t\tmeter_profile_id)) {\n-\t\t\t\tstruct rte_table_action_meter_profile profile;\n-\n-\t\t\t\tmemset(&profile, 0, sizeof(profile));\n-\t\t\t\tprofile.alg = RTE_TABLE_ACTION_METER_TRTCM;\n-\t\t\t\tprofile.trtcm.cir = mp->params.trtcm_rfc2698.cir;\n-\t\t\t\tprofile.trtcm.pir = mp->params.trtcm_rfc2698.pir;\n-\t\t\t\tprofile.trtcm.cbs = mp->params.trtcm_rfc2698.cbs;\n-\t\t\t\tprofile.trtcm.pbs = mp->params.trtcm_rfc2698.pbs;\n-\n-\t\t\t\tstatus = softnic_pipeline_table_mtr_profile_add(softnic,\n-\t\t\t\t\t\tpipeline->name,\n-\t\t\t\t\t\ttable_id,\n-\t\t\t\t\t\tmeter_profile_id,\n-\t\t\t\t\t\t&profile);\n-\t\t\t\tif (status) {\n-\t\t\t\t\trte_flow_error_set(error,\n-\t\t\t\t\t\tEINVAL,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\t\tNULL,\n-\t\t\t\t\t\t\"METER: Table meter profile add failed\");\n-\t\t\t\t\treturn -1;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\t/* Meter policy must exist */\n-\t\t\tpolicy = softnic_mtr_meter_policy_find(softnic,\n-\t\t\t\t\tm->params.meter_policy_id);\n-\t\t\tif (policy == NULL) {\n-\t\t\t\trte_flow_error_set(error,\n-\t\t\t\t\t\tEINVAL,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\t\tNULL,\n-\t\t\t\t\t\t\"METER: fail to find meter policy\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\t\t\t/* RTE_TABLE_ACTION_METER */\n-\t\t\trule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;\n-\t\t\trule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =\n-\t\t\t\tpolicy->policer[RTE_COLOR_GREEN];\n-\t\t\trule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =\n-\t\t\t\tpolicy->policer[RTE_COLOR_YELLOW];\n-\t\t\trule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =\n-\t\t\t\tpolicy->policer[RTE_COLOR_RED];\n-\t\t\trule_action->mtr.tc_mask = 1;\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;\n-\t\t\tbreak;\n-\t\t} /* RTE_FLOW_ACTION_TYPE_METER */\n-\n-\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:\n-\t\t{\n-\t\t\tconst struct rte_flow_action_vxlan_encap *conf =\n-\t\t\t\taction->conf;\n-\t\t\tconst struct rte_flow_item *item;\n-\t\t\tunion flow_item spec, mask;\n-\t\t\tint disabled = 0, status;\n-\t\t\tsize_t size;\n-\n-\t\t\tif (conf == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"VXLAN ENCAP: Null configuration\");\n-\n-\t\t\titem = conf->definition;\n-\t\t\tif (item == NULL)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\taction,\n-\t\t\t\t\t\"VXLAN ENCAP: Null configuration definition\");\n-\n-\t\t\tif (!(params->action_mask &\n-\t\t\t\t\t(1LLU << RTE_TABLE_ACTION_ENCAP)))\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\tNULL,\n-\t\t\t\t\t\"VXLAN ENCAP: Encap action not enabled for this table\");\n-\n-\t\t\t/* Check for Ether. */\n-\t\t\tflow_item_skip_void(&item);\n-\t\t\tstatus = flow_item_proto_preprocess(item, &spec, &mask,\n-\t\t\t\t&size, &disabled, error);\n-\t\t\tif (status)\n-\t\t\t\treturn status;\n-\n-\t\t\tif (item->type != RTE_FLOW_ITEM_TYPE_ETH) {\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\titem,\n-\t\t\t\t\t\"VXLAN ENCAP: first encap item should be ether\");\n-\t\t\t}\n-\t\t\trte_ether_addr_copy(&spec.eth.dst,\n-\t\t\t\t\t&rule_action->encap.vxlan.ether.da);\n-\t\t\trte_ether_addr_copy(&spec.eth.src,\n-\t\t\t\t\t&rule_action->encap.vxlan.ether.sa);\n-\n-\t\t\titem++;\n-\n-\t\t\t/* Check for VLAN. */\n-\t\t\tflow_item_skip_void(&item);\n-\t\t\tstatus = flow_item_proto_preprocess(item, &spec, &mask,\n-\t\t\t\t\t&size, &disabled, error);\n-\t\t\tif (status)\n-\t\t\t\treturn status;\n-\n-\t\t\tif (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {\n-\t\t\t\tif (!params->encap.vxlan.vlan)\n-\t\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\t\tENOTSUP,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\titem,\n-\t\t\t\t\t\t\"VXLAN ENCAP: vlan encap not supported by table\");\n-\n-\t\t\t\tuint16_t tci = rte_ntohs(spec.vlan.tci);\n-\t\t\t\trule_action->encap.vxlan.vlan.pcp =\n-\t\t\t\t\ttci >> 13;\n-\t\t\t\trule_action->encap.vxlan.vlan.dei =\n-\t\t\t\t\t(tci >> 12) & 0x1;\n-\t\t\t\trule_action->encap.vxlan.vlan.vid =\n-\t\t\t\t\ttci & 0xfff;\n-\n-\t\t\t\titem++;\n-\n-\t\t\t\tflow_item_skip_void(&item);\n-\t\t\t\tstatus = flow_item_proto_preprocess(item, &spec,\n-\t\t\t\t\t\t&mask, &size, &disabled, error);\n-\t\t\t\tif (status)\n-\t\t\t\t\treturn status;\n-\t\t\t} else {\n-\t\t\t\tif (params->encap.vxlan.vlan)\n-\t\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\t\tENOTSUP,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\titem,\n-\t\t\t\t\t\t\"VXLAN ENCAP: expecting vlan encap item\");\n-\t\t\t}\n-\n-\t\t\t/* Check for IPV4/IPV6. */\n-\t\t\tswitch (item->type) {\n-\t\t\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n-\t\t\t{\n-\t\t\t\trule_action->encap.vxlan.ipv4.sa =\n-\t\t\t\t\trte_ntohl(spec.ipv4.hdr.src_addr);\n-\t\t\t\trule_action->encap.vxlan.ipv4.da =\n-\t\t\t\t\trte_ntohl(spec.ipv4.hdr.dst_addr);\n-\t\t\t\trule_action->encap.vxlan.ipv4.dscp =\n-\t\t\t\t\tspec.ipv4.hdr.type_of_service >> 2;\n-\t\t\t\trule_action->encap.vxlan.ipv4.ttl =\n-\t\t\t\t\tspec.ipv4.hdr.time_to_live;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n-\t\t\t{\n-\t\t\t\tuint32_t vtc_flow;\n-\n-\t\t\t\tmemcpy(&rule_action->encap.vxlan.ipv6.sa,\n-\t\t\t\t\t\t&spec.ipv6.hdr.src_addr,\n-\t\t\t\t\t\tsizeof(spec.ipv6.hdr.src_addr));\n-\t\t\t\tmemcpy(&rule_action->encap.vxlan.ipv6.da,\n-\t\t\t\t\t\t&spec.ipv6.hdr.dst_addr,\n-\t\t\t\t\t\tsizeof(spec.ipv6.hdr.dst_addr));\n-\t\t\t\tvtc_flow = rte_ntohl(spec.ipv6.hdr.vtc_flow);\n-\t\t\t\trule_action->encap.vxlan.ipv6.flow_label =\n-\t\t\t\t\t\tvtc_flow & 0xfffff;\n-\t\t\t\trule_action->encap.vxlan.ipv6.dscp =\n-\t\t\t\t\t\t(vtc_flow >> 22) & 0x3f;\n-\t\t\t\trule_action->encap.vxlan.ipv6.hop_limit =\n-\t\t\t\t\tspec.ipv6.hdr.hop_limits;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tdefault:\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\titem,\n-\t\t\t\t\t\"VXLAN ENCAP: encap item after ether should be ipv4/ipv6\");\n-\t\t\t}\n-\n-\t\t\titem++;\n-\n-\t\t\t/* Check for UDP. */\n-\t\t\tflow_item_skip_void(&item);\n-\t\t\tstatus = flow_item_proto_preprocess(item, &spec, &mask,\n-\t\t\t\t\t&size, &disabled, error);\n-\t\t\tif (status)\n-\t\t\t\treturn status;\n-\n-\t\t\tif (item->type != RTE_FLOW_ITEM_TYPE_UDP) {\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\titem,\n-\t\t\t\t\t\"VXLAN ENCAP: encap item after ipv4/ipv6 should be udp\");\n-\t\t\t}\n-\t\t\trule_action->encap.vxlan.udp.sp =\n-\t\t\t\trte_ntohs(spec.udp.hdr.src_port);\n-\t\t\trule_action->encap.vxlan.udp.dp =\n-\t\t\t\trte_ntohs(spec.udp.hdr.dst_port);\n-\n-\t\t\titem++;\n-\n-\t\t\t/* Check for VXLAN. */\n-\t\t\tflow_item_skip_void(&item);\n-\t\t\tstatus = flow_item_proto_preprocess(item, &spec, &mask,\n-\t\t\t\t\t&size, &disabled, error);\n-\t\t\tif (status)\n-\t\t\t\treturn status;\n-\n-\t\t\tif (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) {\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\titem,\n-\t\t\t\t\t\"VXLAN ENCAP: encap item after udp should be vxlan\");\n-\t\t\t}\n-\t\t\trule_action->encap.vxlan.vxlan.vni =\n-\t\t\t\t(spec.vxlan.vni[0] << 16U |\n-\t\t\t\t\tspec.vxlan.vni[1] << 8U\n-\t\t\t\t\t| spec.vxlan.vni[2]);\n-\n-\t\t\titem++;\n-\n-\t\t\t/* Check for END. */\n-\t\t\tflow_item_skip_void(&item);\n-\n-\t\t\tif (item->type != RTE_FLOW_ITEM_TYPE_END)\n-\t\t\t\treturn rte_flow_error_set(error,\n-\t\t\t\t\tEINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\titem,\n-\t\t\t\t\t\"VXLAN ENCAP: expecting END item\");\n-\n-\t\t\trule_action->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;\n-\t\t\trule_action->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;\n-\t\t\tbreak;\n-\t\t} /* RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP */\n-\n-\t\tdefault:\n-\t\t\treturn -ENOTSUP;\n-\t\t}\n-\t}\n-\n-\tif (n_jump_queue_rss_drop == 0)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\taction,\n-\t\t\t\"Flow does not have any terminating action\");\n-\n-\treturn 0;\n-}\n-\n-static int\n-pmd_flow_validate(struct rte_eth_dev *dev,\n-\t\tconst struct rte_flow_attr *attr,\n-\t\tconst struct rte_flow_item item[],\n-\t\tconst struct rte_flow_action action[],\n-\t\tstruct rte_flow_error *error)\n-{\n-\tstruct softnic_table_rule_match rule_match;\n-\tstruct softnic_table_rule_action rule_action;\n-\n-\tstruct pmd_internals *softnic = dev->data->dev_private;\n-\tstruct pipeline *pipeline;\n-\tstruct softnic_table *table;\n-\tconst char *pipeline_name = NULL;\n-\tuint32_t table_id = 0;\n-\tint status;\n-\n-\t/* Check input parameters. */\n-\tif (attr == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ATTR,\n-\t\t\t\tNULL, \"Null attr\");\n-\n-\tif (item == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\tNULL,\n-\t\t\t\t\"Null item\");\n-\n-\tif (action == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\tNULL,\n-\t\t\t\t\"Null action\");\n-\n-\t/* Identify the pipeline table to add this flow to. */\n-\tstatus = flow_pipeline_table_get(softnic, attr, &pipeline_name,\n-\t\t\t\t\t&table_id, error);\n-\tif (status)\n-\t\treturn status;\n-\n-\tpipeline = softnic_pipeline_find(softnic, pipeline_name);\n-\tif (pipeline == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\tNULL,\n-\t\t\t\t\"Invalid pipeline name\");\n-\n-\tif (table_id >= pipeline->n_tables)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\t\tEINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\tNULL,\n-\t\t\t\t\"Invalid pipeline table ID\");\n-\n-\ttable = &pipeline->table[table_id];\n-\n-\t/* Rule match. */\n-\tmemset(&rule_match, 0, sizeof(rule_match));\n-\tstatus = flow_rule_match_get(softnic,\n-\t\t\tpipeline,\n-\t\t\ttable,\n-\t\t\tattr,\n-\t\t\titem,\n-\t\t\t&rule_match,\n-\t\t\terror);\n-\tif (status)\n-\t\treturn status;\n-\n-\t/* Rule action. */\n-\tmemset(&rule_action, 0, sizeof(rule_action));\n-\tstatus = flow_rule_action_get(softnic,\n-\t\tpipeline,\n-\t\ttable,\n-\t\tattr,\n-\t\taction,\n-\t\t&rule_action,\n-\t\terror);\n-\tif (status)\n-\t\treturn status;\n-\n-\treturn 0;\n-}\n-\n-static struct softnic_mtr *\n-flow_action_meter_get(struct pmd_internals *softnic,\n-\tconst struct rte_flow_action *action)\n-{\n-\tfor ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++)\n-\t\tif (action->type == RTE_FLOW_ACTION_TYPE_METER) {\n-\t\t\tconst struct rte_flow_action_meter *conf = action->conf;\n-\n-\t\t\tif (conf == NULL)\n-\t\t\t\treturn NULL;\n-\n-\t\t\treturn softnic_mtr_find(softnic, conf->mtr_id);\n-\t\t}\n-\n-\treturn NULL;\n-}\n-\n-static void\n-flow_meter_owner_reset(struct pmd_internals *softnic,\n-\tstruct rte_flow *flow)\n-{\n-\tstruct softnic_mtr_list *ml = &softnic->mtr.mtrs;\n-\tstruct softnic_mtr *m;\n-\n-\tTAILQ_FOREACH(m, ml, node)\n-\t\tif (m->flow == flow) {\n-\t\t\tm->flow = NULL;\n-\t\t\tbreak;\n-\t\t}\n-}\n-\n-static void\n-flow_meter_owner_set(struct pmd_internals *softnic,\n-\tstruct rte_flow *flow,\n-\tstruct softnic_mtr *mtr)\n-{\n-\t/* Reset current flow meter  */\n-\tflow_meter_owner_reset(softnic, flow);\n-\n-\t/* Set new flow meter */\n-\tmtr->flow = flow;\n-}\n-\n-static int\n-is_meter_action_enable(struct pmd_internals *softnic,\n-\tstruct softnic_table *table)\n-{\n-\tstruct softnic_table_action_profile *profile =\n-\t\tsoftnic_table_action_profile_find(softnic,\n-\t\t\ttable->params.action_profile_name);\n-\tstruct softnic_table_action_profile_params *params = &profile->params;\n-\n-\treturn (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) ? 1 : 0;\n-}\n-\n-static struct rte_flow *\n-pmd_flow_create(struct rte_eth_dev *dev,\n-\tconst struct rte_flow_attr *attr,\n-\tconst struct rte_flow_item item[],\n-\tconst struct rte_flow_action action[],\n-\tstruct rte_flow_error *error)\n-{\n-\tstruct softnic_table_rule_match rule_match;\n-\tstruct softnic_table_rule_action rule_action;\n-\tvoid *rule_data;\n-\n-\tstruct pmd_internals *softnic = dev->data->dev_private;\n-\tstruct pipeline *pipeline;\n-\tstruct softnic_table *table;\n-\tstruct rte_flow *flow;\n-\tstruct softnic_mtr *mtr;\n-\tconst char *pipeline_name = NULL;\n-\tuint32_t table_id = 0;\n-\tint new_flow, status;\n-\n-\t/* Check input parameters. */\n-\tif (attr == NULL) {\n-\t\trte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ATTR,\n-\t\t\tNULL,\n-\t\t\t\"Null attr\");\n-\t\treturn NULL;\n-\t}\n-\n-\tif (item == NULL) {\n-\t\trte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\tNULL,\n-\t\t\t\"Null item\");\n-\t\treturn NULL;\n-\t}\n-\n-\tif (action == NULL) {\n-\t\trte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\tNULL,\n-\t\t\t\"Null action\");\n-\t\treturn NULL;\n-\t}\n-\n-\t/* Identify the pipeline table to add this flow to. */\n-\tstatus = flow_pipeline_table_get(softnic, attr, &pipeline_name,\n-\t\t\t\t\t&table_id, error);\n-\tif (status)\n-\t\treturn NULL;\n-\n-\tpipeline = softnic_pipeline_find(softnic, pipeline_name);\n-\tif (pipeline == NULL) {\n-\t\trte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"Invalid pipeline name\");\n-\t\treturn NULL;\n-\t}\n-\n-\tif (table_id >= pipeline->n_tables) {\n-\t\trte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"Invalid pipeline table ID\");\n-\t\treturn NULL;\n-\t}\n-\n-\ttable = &pipeline->table[table_id];\n-\n-\t/* Rule match. */\n-\tmemset(&rule_match, 0, sizeof(rule_match));\n-\tstatus = flow_rule_match_get(softnic,\n-\t\tpipeline,\n-\t\ttable,\n-\t\tattr,\n-\t\titem,\n-\t\t&rule_match,\n-\t\terror);\n-\tif (status)\n-\t\treturn NULL;\n-\n-\t/* Rule action. */\n-\tmemset(&rule_action, 0, sizeof(rule_action));\n-\tstatus = flow_rule_action_get(softnic,\n-\t\tpipeline,\n-\t\ttable,\n-\t\tattr,\n-\t\taction,\n-\t\t&rule_action,\n-\t\terror);\n-\tif (status)\n-\t\treturn NULL;\n-\n-\t/* Flow find/allocate. */\n-\tnew_flow = 0;\n-\tflow = softnic_flow_find(table, &rule_match);\n-\tif (flow == NULL) {\n-\t\tnew_flow = 1;\n-\t\tflow = calloc(1, sizeof(struct rte_flow));\n-\t\tif (flow == NULL) {\n-\t\t\trte_flow_error_set(error,\n-\t\t\t\tENOMEM,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\tNULL,\n-\t\t\t\t\"Not enough memory for new flow\");\n-\t\t\treturn NULL;\n-\t\t}\n-\t}\n-\n-\t/* Rule add. */\n-\tstatus = softnic_pipeline_table_rule_add(softnic,\n-\t\tpipeline_name,\n-\t\ttable_id,\n-\t\t&rule_match,\n-\t\t&rule_action,\n-\t\t&rule_data);\n-\tif (status) {\n-\t\tif (new_flow)\n-\t\t\tfree(flow);\n-\n-\t\trte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"Pipeline table rule add failed\");\n-\t\treturn NULL;\n-\t}\n-\n-\t/* Flow fill in. */\n-\tmemcpy(&flow->match, &rule_match, sizeof(rule_match));\n-\tmemcpy(&flow->action, &rule_action, sizeof(rule_action));\n-\tflow->data = rule_data;\n-\tflow->pipeline = pipeline;\n-\tflow->table_id = table_id;\n-\n-\tmtr = flow_action_meter_get(softnic, action);\n-\tif (mtr)\n-\t\tflow_meter_owner_set(softnic, flow, mtr);\n-\n-\t/* Flow add to list. */\n-\tif (new_flow)\n-\t\tTAILQ_INSERT_TAIL(&table->flows, flow, node);\n-\n-\treturn flow;\n-}\n-\n-static int\n-pmd_flow_destroy(struct rte_eth_dev *dev,\n-\tstruct rte_flow *flow,\n-\tstruct rte_flow_error *error)\n-{\n-\tstruct pmd_internals *softnic = dev->data->dev_private;\n-\tstruct softnic_table *table;\n-\tint status;\n-\n-\t/* Check input parameters. */\n-\tif (flow == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_HANDLE,\n-\t\t\tNULL,\n-\t\t\t\"Null flow\");\n-\n-\ttable = &flow->pipeline->table[flow->table_id];\n-\n-\t/* Rule delete. */\n-\tstatus = softnic_pipeline_table_rule_delete(softnic,\n-\t\tflow->pipeline->name,\n-\t\tflow->table_id,\n-\t\t&flow->match);\n-\tif (status)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"Pipeline table rule delete failed\");\n-\n-\t/* Update dependencies */\n-\tif (is_meter_action_enable(softnic, table))\n-\t\tflow_meter_owner_reset(softnic, flow);\n-\n-\t/* Flow delete. */\n-\tTAILQ_REMOVE(&table->flows, flow, node);\n-\tfree(flow);\n-\n-\treturn 0;\n-}\n-\n-static int\n-pmd_flow_flush(struct rte_eth_dev *dev,\n-\tstruct rte_flow_error *error)\n-{\n-\tstruct pmd_internals *softnic = dev->data->dev_private;\n-\tstruct pipeline *pipeline;\n-\tint fail_to_del_rule = 0;\n-\tuint32_t i;\n-\n-\tTAILQ_FOREACH(pipeline, &softnic->pipeline_list, node) {\n-\t\t/* Remove all the flows added to the tables. */\n-\t\tfor (i = 0; i < pipeline->n_tables; i++) {\n-\t\t\tstruct softnic_table *table = &pipeline->table[i];\n-\t\t\tstruct rte_flow *flow;\n-\t\t\tvoid *temp;\n-\t\t\tint status;\n-\n-\t\t\tRTE_TAILQ_FOREACH_SAFE(flow, &table->flows, node,\n-\t\t\t\ttemp) {\n-\t\t\t\t/* Rule delete. */\n-\t\t\t\tstatus = softnic_pipeline_table_rule_delete\n-\t\t\t\t\t\t(softnic,\n-\t\t\t\t\t\tpipeline->name,\n-\t\t\t\t\t\ti,\n-\t\t\t\t\t\t&flow->match);\n-\t\t\t\tif (status)\n-\t\t\t\t\tfail_to_del_rule = 1;\n-\t\t\t\t/* Update dependencies */\n-\t\t\t\tif (is_meter_action_enable(softnic, table))\n-\t\t\t\t\tflow_meter_owner_reset(softnic, flow);\n-\n-\t\t\t\t/* Flow delete. */\n-\t\t\t\tTAILQ_REMOVE(&table->flows, flow, node);\n-\t\t\t\tfree(flow);\n-\t\t\t}\n-\t\t}\n-\t}\n-\n-\tif (fail_to_del_rule)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"Some of the rules could not be deleted\");\n-\n-\treturn 0;\n-}\n-\n-static int\n-pmd_flow_query(struct rte_eth_dev *dev __rte_unused,\n-\tstruct rte_flow *flow,\n-\tconst struct rte_flow_action *action __rte_unused,\n-\tvoid *data,\n-\tstruct rte_flow_error *error)\n-{\n-\tstruct rte_table_action_stats_counters stats;\n-\tstruct softnic_table *table;\n-\tstruct rte_flow_query_count *flow_stats = data;\n-\tint status;\n-\n-\t/* Check input parameters. */\n-\tif (flow == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_HANDLE,\n-\t\t\tNULL,\n-\t\t\t\"Null flow\");\n-\n-\tif (data == NULL)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"Null data\");\n-\n-\ttable = &flow->pipeline->table[flow->table_id];\n-\n-\t/* Rule stats read. */\n-\tstatus = rte_table_action_stats_read(table->a,\n-\t\tflow->data,\n-\t\t&stats,\n-\t\tflow_stats->reset);\n-\tif (status)\n-\t\treturn rte_flow_error_set(error,\n-\t\t\tEINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\tNULL,\n-\t\t\t\"Pipeline table rule stats read failed\");\n-\n-\t/* Fill in flow stats. */\n-\tflow_stats->hits_set =\n-\t\t(table->ap->params.stats.n_packets_enabled) ? 1 : 0;\n-\tflow_stats->bytes_set =\n-\t\t(table->ap->params.stats.n_bytes_enabled) ? 1 : 0;\n-\tflow_stats->hits = stats.n_packets;\n-\tflow_stats->bytes = stats.n_bytes;\n-\n-\treturn 0;\n-}\n-\n-const struct rte_flow_ops pmd_flow_ops = {\n-\t.validate = pmd_flow_validate,\n-\t.create = pmd_flow_create,\n-\t.destroy = pmd_flow_destroy,\n-\t.flush = pmd_flow_flush,\n-\t.query = pmd_flow_query,\n-\t.isolate = NULL,\n-};\n",
    "prefixes": [
        "02/21"
    ]
}