get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 50610,
    "url": "http://patches.dpdk.org/api/patches/50610/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20190228070317.17002-14-hyonkim@cisco.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": "<20190228070317.17002-14-hyonkim@cisco.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190228070317.17002-14-hyonkim@cisco.com",
    "date": "2019-02-28T07:03:15",
    "name": "[13/15] net/enic: fix several issues with inner packet matching",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "777f2f5c8ba70da5e2a2e6241cb7dbe7e100fd0e",
    "submitter": {
        "id": 948,
        "url": "http://patches.dpdk.org/api/people/948/?format=api",
        "name": "Hyong Youb Kim (hyonkim)",
        "email": "hyonkim@cisco.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20190228070317.17002-14-hyonkim@cisco.com/mbox/",
    "series": [
        {
            "id": 3568,
            "url": "http://patches.dpdk.org/api/series/3568/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=3568",
            "date": "2019-02-28T07:03:02",
            "name": "net/enic: 19.05 updates",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/3568/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/50610/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/50610/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id A7F2E4CA6;\n\tThu, 28 Feb 2019 08:06:34 +0100 (CET)",
            "from alln-iport-6.cisco.com (alln-iport-6.cisco.com\n\t[173.37.142.93]) by dpdk.org (Postfix) with ESMTP id E667C4CA6\n\tfor <dev@dpdk.org>; Thu, 28 Feb 2019 08:06:32 +0100 (CET)",
            "from alln-core-5.cisco.com ([173.36.13.138])\n\tby alln-iport-6.cisco.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t28 Feb 2019 07:06:32 +0000",
            "from cisco.com (savbu-usnic-a.cisco.com [10.193.184.48])\n\tby alln-core-5.cisco.com (8.15.2/8.15.2) with ESMTP id x1S76VIQ022661;\n\tThu, 28 Feb 2019 07:06:32 GMT",
            "by cisco.com (Postfix, from userid 508933)\n\tid C568B20F2001; Wed, 27 Feb 2019 23:06:31 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n\td=cisco.com; i=@cisco.com; l=26366; q=dns/txt;\n\ts=iport; t=1551337593; x=1552547193;\n\th=from:to:cc:subject:date:message-id:in-reply-to: references;\n\tbh=12Ye7idERSgT0gdcFl812cMzRIpyP38wqKOjf96ENJQ=;\n\tb=UHBLwTr7ptCNL7skxFY+azvzhPeL17uTkxRpfFRY4v1tNRnejwMYK+MY\n\ttCF78qd8kALnWj3HUJniSAMd9om/D4NQkxMMgBFO+UbLNoEPnToV23v0L\n\ty3Dy+5Kq3zg+UangirFurwpdHQ9RZw92u/6xWNWDkEbBtISR/V/jH3d8w I=;",
        "X-IronPort-AV": "E=Sophos;i=\"5.58,422,1544486400\"; d=\"scan'208\";a=\"241773764\"",
        "From": "Hyong Youb Kim <hyonkim@cisco.com>",
        "To": "Ferruh Yigit <ferruh.yigit@intel.com>",
        "Cc": "dev@dpdk.org, John Daley <johndale@cisco.com>,\n\tHyong Youb Kim <hyonkim@cisco.com>",
        "Date": "Wed, 27 Feb 2019 23:03:15 -0800",
        "Message-Id": "<20190228070317.17002-14-hyonkim@cisco.com>",
        "X-Mailer": "git-send-email 2.16.2",
        "In-Reply-To": "<20190228070317.17002-1-hyonkim@cisco.com>",
        "References": "<20190228070317.17002-1-hyonkim@cisco.com>",
        "X-Outbound-SMTP-Client": "10.193.184.48, savbu-usnic-a.cisco.com",
        "X-Outbound-Node": "alln-core-5.cisco.com",
        "Subject": "[dpdk-dev] [PATCH 13/15] net/enic: fix several issues with inner\n\tpacket matching",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Inner packet matching is currently buggy in many cases.\n\n1. Mishandling null spec (\"match any\").\nThe copy_item functions do nothing if spec is null. This is incorrect,\nas all patterns should be appended to the L5 pattern buffer even for\nnull spec (treated as all zeros).\n\n2. Accessing null spec causing segfault.\n\n3. Not setting protocol fields.\nThe NIC filter API currently has no flags for \"match inner IPv4, IPv6,\nUDP, TCP, and so on\". So, the driver needs to explicitly set EtherType\nand IP protocol fields in the L5 pattern buffer to avoid false\npositives (e.g. reporting IPv6 as IPv4).\n\nInstead of keep adding \"if inner, do something differently\" cases to\nthe existing copy_item functions, introduce separate functions for\ninner packet patterns and address the above issues in those\nfunctions. The changes to the previous outer-packet copy_item\nfunctions are mechanical, due to reduced indentation.\n\nFixes: 6ced137607d0 (\"net/enic: flow API for NICs with advanced filters enabled\")\n\nSigned-off-by: Hyong Youb Kim <hyonkim@cisco.com>\n---\n drivers/net/enic/enic_flow.c | 371 ++++++++++++++++++++++++++-----------------\n 1 file changed, 224 insertions(+), 147 deletions(-)",
    "diff": "diff --git a/drivers/net/enic/enic_flow.c b/drivers/net/enic/enic_flow.c\nindex b3172e7be..5924a01e3 100644\n--- a/drivers/net/enic/enic_flow.c\n+++ b/drivers/net/enic/enic_flow.c\n@@ -30,11 +30,15 @@\n  * filter: Partially filled in NIC filter structure.\n  * inner_ofst: If zero, this is an outer header. If non-zero, this is\n  *   the offset into L5 where the header begins.\n+ * l2_proto_off: offset to EtherType eth or vlan header.\n+ * l3_proto_off: offset to next protocol field in IPv4 or 6 header.\n  */\n struct copy_item_args {\n \tconst struct rte_flow_item *item;\n \tstruct filter_v2 *filter;\n \tuint8_t *inner_ofst;\n+\tuint8_t l2_proto_off;\n+\tuint8_t l3_proto_off;\n };\n \n /* functions for copying items into enic filters */\n@@ -50,6 +54,8 @@ struct enic_items {\n \t * versions, it's invalid to start the stack above layer 3.\n \t */\n \tconst u8 valid_start_item;\n+\t/* Inner packet version of copy_item. */\n+\tenic_copy_item_fn *inner_copy_item;\n };\n \n /** Filtering capabilities for various NIC and firmware versions. */\n@@ -86,6 +92,12 @@ static enic_copy_item_fn enic_copy_item_udp_v2;\n static enic_copy_item_fn enic_copy_item_tcp_v2;\n static enic_copy_item_fn enic_copy_item_sctp_v2;\n static enic_copy_item_fn enic_copy_item_vxlan_v2;\n+static enic_copy_item_fn enic_copy_item_inner_eth_v2;\n+static enic_copy_item_fn enic_copy_item_inner_vlan_v2;\n+static enic_copy_item_fn enic_copy_item_inner_ipv4_v2;\n+static enic_copy_item_fn enic_copy_item_inner_ipv6_v2;\n+static enic_copy_item_fn enic_copy_item_inner_udp_v2;\n+static enic_copy_item_fn enic_copy_item_inner_tcp_v2;\n static copy_action_fn enic_copy_action_v1;\n static copy_action_fn enic_copy_action_v2;\n \n@@ -100,6 +112,7 @@ static const struct enic_items enic_items_v1[] = {\n \t\t.prev_items = (const enum rte_flow_item_type[]) {\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_UDP] = {\n \t\t.copy_item = enic_copy_item_udp_v1,\n@@ -108,6 +121,7 @@ static const struct enic_items enic_items_v1[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_IPV4,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_TCP] = {\n \t\t.copy_item = enic_copy_item_tcp_v1,\n@@ -116,6 +130,7 @@ static const struct enic_items enic_items_v1[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_IPV4,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n };\n \n@@ -131,6 +146,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_UDP,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_ETH] = {\n \t\t.copy_item = enic_copy_item_eth_v2,\n@@ -139,6 +155,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_VXLAN,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_eth_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_VLAN] = {\n \t\t.copy_item = enic_copy_item_vlan_v2,\n@@ -147,6 +164,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_ETH,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_vlan_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_IPV4] = {\n \t\t.copy_item = enic_copy_item_ipv4_v2,\n@@ -156,6 +174,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_VLAN,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_ipv4_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_IPV6] = {\n \t\t.copy_item = enic_copy_item_ipv6_v2,\n@@ -165,6 +184,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_VLAN,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_ipv6_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_UDP] = {\n \t\t.copy_item = enic_copy_item_udp_v2,\n@@ -174,6 +194,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_IPV6,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_udp_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_TCP] = {\n \t\t.copy_item = enic_copy_item_tcp_v2,\n@@ -183,6 +204,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_IPV6,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_tcp_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_SCTP] = {\n \t\t.copy_item = enic_copy_item_sctp_v2,\n@@ -192,6 +214,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_IPV6,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_VXLAN] = {\n \t\t.copy_item = enic_copy_item_vxlan_v2,\n@@ -200,6 +223,7 @@ static const struct enic_items enic_items_v2[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_UDP,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n };\n \n@@ -212,6 +236,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_UDP,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_ETH] = {\n \t\t.copy_item = enic_copy_item_eth_v2,\n@@ -220,6 +245,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_VXLAN,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_eth_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_VLAN] = {\n \t\t.copy_item = enic_copy_item_vlan_v2,\n@@ -228,6 +254,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_ETH,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_vlan_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_IPV4] = {\n \t\t.copy_item = enic_copy_item_ipv4_v2,\n@@ -237,6 +264,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_VLAN,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_ipv4_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_IPV6] = {\n \t\t.copy_item = enic_copy_item_ipv6_v2,\n@@ -246,6 +274,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_VLAN,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_ipv6_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_UDP] = {\n \t\t.copy_item = enic_copy_item_udp_v2,\n@@ -255,6 +284,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_IPV6,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_udp_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_TCP] = {\n \t\t.copy_item = enic_copy_item_tcp_v2,\n@@ -264,6 +294,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_IPV6,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = enic_copy_item_inner_tcp_v2,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_SCTP] = {\n \t\t.copy_item = enic_copy_item_sctp_v2,\n@@ -273,6 +304,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_IPV6,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n \t[RTE_FLOW_ITEM_TYPE_VXLAN] = {\n \t\t.copy_item = enic_copy_item_vxlan_v2,\n@@ -281,6 +313,7 @@ static const struct enic_items enic_items_v3[] = {\n \t\t\t       RTE_FLOW_ITEM_TYPE_UDP,\n \t\t\t       RTE_FLOW_ITEM_TYPE_END,\n \t\t},\n+\t\t.inner_copy_item = NULL,\n \t},\n };\n \n@@ -374,7 +407,6 @@ enic_copy_item_ipv4_v1(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_ipv4 *spec = item->spec;\n \tconst struct rte_flow_item_ipv4 *mask = item->mask;\n \tstruct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;\n@@ -385,9 +417,6 @@ enic_copy_item_ipv4_v1(struct copy_item_args *arg)\n \n \tFLOW_TRACE();\n \n-\tif (*inner_ofst)\n-\t\treturn ENOTSUP;\n-\n \tif (!mask)\n \t\tmask = &rte_flow_item_ipv4_mask;\n \n@@ -416,7 +445,6 @@ enic_copy_item_udp_v1(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_udp *spec = item->spec;\n \tconst struct rte_flow_item_udp *mask = item->mask;\n \tstruct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;\n@@ -427,9 +455,6 @@ enic_copy_item_udp_v1(struct copy_item_args *arg)\n \n \tFLOW_TRACE();\n \n-\tif (*inner_ofst)\n-\t\treturn ENOTSUP;\n-\n \tif (!mask)\n \t\tmask = &rte_flow_item_udp_mask;\n \n@@ -459,7 +484,6 @@ enic_copy_item_tcp_v1(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_tcp *spec = item->spec;\n \tconst struct rte_flow_item_tcp *mask = item->mask;\n \tstruct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;\n@@ -470,9 +494,6 @@ enic_copy_item_tcp_v1(struct copy_item_args *arg)\n \n \tFLOW_TRACE();\n \n-\tif (*inner_ofst)\n-\t\treturn ENOTSUP;\n-\n \tif (!mask)\n \t\tmask = &rte_flow_item_tcp_mask;\n \n@@ -497,12 +518,150 @@ enic_copy_item_tcp_v1(struct copy_item_args *arg)\n \treturn 0;\n }\n \n+/*\n+ * The common 'copy' function for all inner packet patterns. Patterns are\n+ * first appended to the L5 pattern buffer. Then, since the NIC filter\n+ * API has no special support for inner packet matching at the moment,\n+ * we set EtherType and IP proto as necessary.\n+ */\n+static int\n+copy_inner_common(struct filter_generic_1 *gp, uint8_t *inner_ofst,\n+\t\t  const void *val, const void *mask, uint8_t val_size,\n+\t\t  uint8_t proto_off, uint16_t proto_val, uint8_t proto_size)\n+{\n+\tuint8_t *l5_mask, *l5_val;\n+\tuint8_t start_off;\n+\n+\t/* No space left in the L5 pattern buffer. */\n+\tstart_off = *inner_ofst;\n+\tif ((start_off + val_size) > FILTER_GENERIC_1_KEY_LEN)\n+\t\treturn ENOTSUP;\n+\tl5_mask = gp->layer[FILTER_GENERIC_1_L5].mask;\n+\tl5_val = gp->layer[FILTER_GENERIC_1_L5].val;\n+\t/* Copy the pattern into the L5 buffer. */\n+\tif (val) {\n+\t\tmemcpy(l5_mask + start_off, mask, val_size);\n+\t\tmemcpy(l5_val + start_off, val, val_size);\n+\t}\n+\t/* Set the protocol field in the previous header. */\n+\tif (proto_off) {\n+\t\tvoid *m, *v;\n+\n+\t\tm = l5_mask + proto_off;\n+\t\tv = l5_val + proto_off;\n+\t\tif (proto_size == 1) {\n+\t\t\t*(uint8_t *)m = 0xff;\n+\t\t\t*(uint8_t *)v = (uint8_t)proto_val;\n+\t\t} else if (proto_size == 2) {\n+\t\t\t*(uint16_t *)m = 0xffff;\n+\t\t\t*(uint16_t *)v = proto_val;\n+\t\t}\n+\t}\n+\t/* All inner headers land in L5 buffer even if their spec is null. */\n+\t*inner_ofst += val_size;\n+\treturn 0;\n+}\n+\n+static int\n+enic_copy_item_inner_eth_v2(struct copy_item_args *arg)\n+{\n+\tconst void *mask = arg->item->mask;\n+\tuint8_t *off = arg->inner_ofst;\n+\n+\tFLOW_TRACE();\n+\tif (!mask)\n+\t\tmask = &rte_flow_item_eth_mask;\n+\targ->l2_proto_off = *off + offsetof(struct ether_hdr, ether_type);\n+\treturn copy_inner_common(&arg->filter->u.generic_1, off,\n+\t\targ->item->spec, mask, sizeof(struct ether_hdr),\n+\t\t0 /* no previous protocol */, 0, 0);\n+}\n+\n+static int\n+enic_copy_item_inner_vlan_v2(struct copy_item_args *arg)\n+{\n+\tconst void *mask = arg->item->mask;\n+\tuint8_t *off = arg->inner_ofst;\n+\tuint8_t eth_type_off;\n+\n+\tFLOW_TRACE();\n+\tif (!mask)\n+\t\tmask = &rte_flow_item_vlan_mask;\n+\t/* Append vlan header to L5 and set ether type = TPID */\n+\teth_type_off = arg->l2_proto_off;\n+\targ->l2_proto_off = *off + offsetof(struct vlan_hdr, eth_proto);\n+\treturn copy_inner_common(&arg->filter->u.generic_1, off,\n+\t\targ->item->spec, mask, sizeof(struct vlan_hdr),\n+\t\teth_type_off, rte_cpu_to_be_16(ETHER_TYPE_VLAN), 2);\n+}\n+\n+static int\n+enic_copy_item_inner_ipv4_v2(struct copy_item_args *arg)\n+{\n+\tconst void *mask = arg->item->mask;\n+\tuint8_t *off = arg->inner_ofst;\n+\n+\tFLOW_TRACE();\n+\tif (!mask)\n+\t\tmask = &rte_flow_item_ipv4_mask;\n+\t/* Append ipv4 header to L5 and set ether type = ipv4 */\n+\targ->l3_proto_off = *off + offsetof(struct ipv4_hdr, next_proto_id);\n+\treturn copy_inner_common(&arg->filter->u.generic_1, off,\n+\t\targ->item->spec, mask, sizeof(struct ipv4_hdr),\n+\t\targ->l2_proto_off, rte_cpu_to_be_16(ETHER_TYPE_IPv4), 2);\n+}\n+\n+static int\n+enic_copy_item_inner_ipv6_v2(struct copy_item_args *arg)\n+{\n+\tconst void *mask = arg->item->mask;\n+\tuint8_t *off = arg->inner_ofst;\n+\n+\tFLOW_TRACE();\n+\tif (!mask)\n+\t\tmask = &rte_flow_item_ipv6_mask;\n+\t/* Append ipv6 header to L5 and set ether type = ipv6 */\n+\targ->l3_proto_off = *off + offsetof(struct ipv6_hdr, proto);\n+\treturn copy_inner_common(&arg->filter->u.generic_1, off,\n+\t\targ->item->spec, mask, sizeof(struct ipv6_hdr),\n+\t\targ->l2_proto_off, rte_cpu_to_be_16(ETHER_TYPE_IPv6), 2);\n+}\n+\n+static int\n+enic_copy_item_inner_udp_v2(struct copy_item_args *arg)\n+{\n+\tconst void *mask = arg->item->mask;\n+\tuint8_t *off = arg->inner_ofst;\n+\n+\tFLOW_TRACE();\n+\tif (!mask)\n+\t\tmask = &rte_flow_item_udp_mask;\n+\t/* Append udp header to L5 and set ip proto = udp */\n+\treturn copy_inner_common(&arg->filter->u.generic_1, off,\n+\t\targ->item->spec, mask, sizeof(struct udp_hdr),\n+\t\targ->l3_proto_off, IPPROTO_UDP, 1);\n+}\n+\n+static int\n+enic_copy_item_inner_tcp_v2(struct copy_item_args *arg)\n+{\n+\tconst void *mask = arg->item->mask;\n+\tuint8_t *off = arg->inner_ofst;\n+\n+\tFLOW_TRACE();\n+\tif (!mask)\n+\t\tmask = &rte_flow_item_tcp_mask;\n+\t/* Append tcp header to L5 and set ip proto = tcp */\n+\treturn copy_inner_common(&arg->filter->u.generic_1, off,\n+\t\targ->item->spec, mask, sizeof(struct tcp_hdr),\n+\t\targ->l3_proto_off, IPPROTO_TCP, 1);\n+}\n+\n static int\n enic_copy_item_eth_v2(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tstruct ether_hdr enic_spec;\n \tstruct ether_hdr enic_mask;\n \tconst struct rte_flow_item_eth *spec = item->spec;\n@@ -530,24 +689,11 @@ enic_copy_item_eth_v2(struct copy_item_args *arg)\n \tenic_spec.ether_type = spec->type;\n \tenic_mask.ether_type = mask->type;\n \n-\tif (*inner_ofst == 0) {\n-\t\t/* outer header */\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L2].mask, &enic_mask,\n-\t\t       sizeof(struct ether_hdr));\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L2].val, &enic_spec,\n-\t\t       sizeof(struct ether_hdr));\n-\t} else {\n-\t\t/* inner header */\n-\t\tif ((*inner_ofst + sizeof(struct ether_hdr)) >\n-\t\t     FILTER_GENERIC_1_KEY_LEN)\n-\t\t\treturn ENOTSUP;\n-\t\t/* Offset into L5 where inner Ethernet header goes */\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],\n-\t\t       &enic_mask, sizeof(struct ether_hdr));\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],\n-\t\t       &enic_spec, sizeof(struct ether_hdr));\n-\t\t*inner_ofst += sizeof(struct ether_hdr);\n-\t}\n+\t/* outer header */\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L2].mask, &enic_mask,\n+\t       sizeof(struct ether_hdr));\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L2].val, &enic_spec,\n+\t       sizeof(struct ether_hdr));\n \treturn 0;\n }\n \n@@ -556,10 +702,11 @@ enic_copy_item_vlan_v2(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_vlan *spec = item->spec;\n \tconst struct rte_flow_item_vlan *mask = item->mask;\n \tstruct filter_generic_1 *gp = &enic_filter->u.generic_1;\n+\tstruct ether_hdr *eth_mask;\n+\tstruct ether_hdr *eth_val;\n \n \tFLOW_TRACE();\n \n@@ -570,36 +717,21 @@ enic_copy_item_vlan_v2(struct copy_item_args *arg)\n \tif (!mask)\n \t\tmask = &rte_flow_item_vlan_mask;\n \n-\tif (*inner_ofst == 0) {\n-\t\tstruct ether_hdr *eth_mask =\n-\t\t\t(void *)gp->layer[FILTER_GENERIC_1_L2].mask;\n-\t\tstruct ether_hdr *eth_val =\n-\t\t\t(void *)gp->layer[FILTER_GENERIC_1_L2].val;\n-\n-\t\t/* Outer TPID cannot be matched */\n-\t\tif (eth_mask->ether_type)\n-\t\t\treturn ENOTSUP;\n-\t\t/*\n-\t\t * When packet matching, the VIC always compares vlan-stripped\n-\t\t * L2, regardless of vlan stripping settings. So, the inner type\n-\t\t * from vlan becomes the ether type of the eth header.\n-\t\t */\n-\t\teth_mask->ether_type = mask->inner_type;\n-\t\teth_val->ether_type = spec->inner_type;\n-\t\t/* For TCI, use the vlan mask/val fields (little endian). */\n-\t\tgp->mask_vlan = rte_be_to_cpu_16(mask->tci);\n-\t\tgp->val_vlan = rte_be_to_cpu_16(spec->tci);\n-\t} else {\n-\t\t/* Inner header. Mask/Val start at *inner_ofst into L5 */\n-\t\tif ((*inner_ofst + sizeof(struct vlan_hdr)) >\n-\t\t     FILTER_GENERIC_1_KEY_LEN)\n-\t\t\treturn ENOTSUP;\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],\n-\t\t       mask, sizeof(struct vlan_hdr));\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],\n-\t\t       spec, sizeof(struct vlan_hdr));\n-\t\t*inner_ofst += sizeof(struct vlan_hdr);\n-\t}\n+\teth_mask = (void *)gp->layer[FILTER_GENERIC_1_L2].mask;\n+\teth_val = (void *)gp->layer[FILTER_GENERIC_1_L2].val;\n+\t/* Outer TPID cannot be matched */\n+\tif (eth_mask->ether_type)\n+\t\treturn ENOTSUP;\n+\t/*\n+\t * When packet matching, the VIC always compares vlan-stripped\n+\t * L2, regardless of vlan stripping settings. So, the inner type\n+\t * from vlan becomes the ether type of the eth header.\n+\t */\n+\teth_mask->ether_type = mask->inner_type;\n+\teth_val->ether_type = spec->inner_type;\n+\t/* For TCI, use the vlan mask/val fields (little endian). */\n+\tgp->mask_vlan = rte_be_to_cpu_16(mask->tci);\n+\tgp->val_vlan = rte_be_to_cpu_16(spec->tci);\n \treturn 0;\n }\n \n@@ -608,40 +740,27 @@ enic_copy_item_ipv4_v2(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_ipv4 *spec = item->spec;\n \tconst struct rte_flow_item_ipv4 *mask = item->mask;\n \tstruct filter_generic_1 *gp = &enic_filter->u.generic_1;\n \n \tFLOW_TRACE();\n \n-\tif (*inner_ofst == 0) {\n-\t\t/* Match IPv4 */\n-\t\tgp->mask_flags |= FILTER_GENERIC_1_IPV4;\n-\t\tgp->val_flags |= FILTER_GENERIC_1_IPV4;\n+\t/* Match IPv4 */\n+\tgp->mask_flags |= FILTER_GENERIC_1_IPV4;\n+\tgp->val_flags |= FILTER_GENERIC_1_IPV4;\n \n-\t\t/* Match all if no spec */\n-\t\tif (!spec)\n-\t\t\treturn 0;\n+\t/* Match all if no spec */\n+\tif (!spec)\n+\t\treturn 0;\n \n-\t\tif (!mask)\n-\t\t\tmask = &rte_flow_item_ipv4_mask;\n+\tif (!mask)\n+\t\tmask = &rte_flow_item_ipv4_mask;\n \n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr,\n-\t\t       sizeof(struct ipv4_hdr));\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr,\n-\t\t       sizeof(struct ipv4_hdr));\n-\t} else {\n-\t\t/* Inner IPv4 header. Mask/Val start at *inner_ofst into L5 */\n-\t\tif ((*inner_ofst + sizeof(struct ipv4_hdr)) >\n-\t\t     FILTER_GENERIC_1_KEY_LEN)\n-\t\t\treturn ENOTSUP;\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],\n-\t\t       mask, sizeof(struct ipv4_hdr));\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],\n-\t\t       spec, sizeof(struct ipv4_hdr));\n-\t\t*inner_ofst += sizeof(struct ipv4_hdr);\n-\t}\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr,\n+\t       sizeof(struct ipv4_hdr));\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr,\n+\t       sizeof(struct ipv4_hdr));\n \treturn 0;\n }\n \n@@ -650,7 +769,6 @@ enic_copy_item_ipv6_v2(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_ipv6 *spec = item->spec;\n \tconst struct rte_flow_item_ipv6 *mask = item->mask;\n \tstruct filter_generic_1 *gp = &enic_filter->u.generic_1;\n@@ -668,22 +786,10 @@ enic_copy_item_ipv6_v2(struct copy_item_args *arg)\n \tif (!mask)\n \t\tmask = &rte_flow_item_ipv6_mask;\n \n-\tif (*inner_ofst == 0) {\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr,\n-\t\t       sizeof(struct ipv6_hdr));\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr,\n-\t\t       sizeof(struct ipv6_hdr));\n-\t} else {\n-\t\t/* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */\n-\t\tif ((*inner_ofst + sizeof(struct ipv6_hdr)) >\n-\t\t     FILTER_GENERIC_1_KEY_LEN)\n-\t\t\treturn ENOTSUP;\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],\n-\t\t       mask, sizeof(struct ipv6_hdr));\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],\n-\t\t       spec, sizeof(struct ipv6_hdr));\n-\t\t*inner_ofst += sizeof(struct ipv6_hdr);\n-\t}\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr,\n+\t       sizeof(struct ipv6_hdr));\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr,\n+\t       sizeof(struct ipv6_hdr));\n \treturn 0;\n }\n \n@@ -692,7 +798,6 @@ enic_copy_item_udp_v2(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_udp *spec = item->spec;\n \tconst struct rte_flow_item_udp *mask = item->mask;\n \tstruct filter_generic_1 *gp = &enic_filter->u.generic_1;\n@@ -710,22 +815,10 @@ enic_copy_item_udp_v2(struct copy_item_args *arg)\n \tif (!mask)\n \t\tmask = &rte_flow_item_udp_mask;\n \n-\tif (*inner_ofst == 0) {\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,\n-\t\t       sizeof(struct udp_hdr));\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,\n-\t\t       sizeof(struct udp_hdr));\n-\t} else {\n-\t\t/* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */\n-\t\tif ((*inner_ofst + sizeof(struct udp_hdr)) >\n-\t\t     FILTER_GENERIC_1_KEY_LEN)\n-\t\t\treturn ENOTSUP;\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],\n-\t\t       mask, sizeof(struct udp_hdr));\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],\n-\t\t       spec, sizeof(struct udp_hdr));\n-\t\t*inner_ofst += sizeof(struct udp_hdr);\n-\t}\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,\n+\t       sizeof(struct udp_hdr));\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,\n+\t       sizeof(struct udp_hdr));\n \treturn 0;\n }\n \n@@ -734,7 +827,6 @@ enic_copy_item_tcp_v2(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_tcp *spec = item->spec;\n \tconst struct rte_flow_item_tcp *mask = item->mask;\n \tstruct filter_generic_1 *gp = &enic_filter->u.generic_1;\n@@ -752,22 +844,10 @@ enic_copy_item_tcp_v2(struct copy_item_args *arg)\n \tif (!mask)\n \t\treturn ENOTSUP;\n \n-\tif (*inner_ofst == 0) {\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,\n-\t\t       sizeof(struct tcp_hdr));\n-\t\tmemcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,\n-\t\t       sizeof(struct tcp_hdr));\n-\t} else {\n-\t\t/* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */\n-\t\tif ((*inner_ofst + sizeof(struct tcp_hdr)) >\n-\t\t     FILTER_GENERIC_1_KEY_LEN)\n-\t\t\treturn ENOTSUP;\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],\n-\t\t       mask, sizeof(struct tcp_hdr));\n-\t\tmemcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],\n-\t\t       spec, sizeof(struct tcp_hdr));\n-\t\t*inner_ofst += sizeof(struct tcp_hdr);\n-\t}\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,\n+\t       sizeof(struct tcp_hdr));\n+\tmemcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,\n+\t       sizeof(struct tcp_hdr));\n \treturn 0;\n }\n \n@@ -776,7 +856,6 @@ enic_copy_item_sctp_v2(struct copy_item_args *arg)\n {\n \tconst struct rte_flow_item *item = arg->item;\n \tstruct filter_v2 *enic_filter = arg->filter;\n-\tuint8_t *inner_ofst = arg->inner_ofst;\n \tconst struct rte_flow_item_sctp *spec = item->spec;\n \tconst struct rte_flow_item_sctp *mask = item->mask;\n \tstruct filter_generic_1 *gp = &enic_filter->u.generic_1;\n@@ -785,9 +864,6 @@ enic_copy_item_sctp_v2(struct copy_item_args *arg)\n \n \tFLOW_TRACE();\n \n-\tif (*inner_ofst)\n-\t\treturn ENOTSUP;\n-\n \t/*\n \t * The NIC filter API has no flags for \"match sctp\", so explicitly set\n \t * the protocol number in the IP pattern.\n@@ -838,9 +914,6 @@ enic_copy_item_vxlan_v2(struct copy_item_args *arg)\n \n \tFLOW_TRACE();\n \n-\tif (*inner_ofst)\n-\t\treturn EINVAL;\n-\n \t/*\n \t * The NIC filter API has no flags for \"match vxlan\". Set UDP port to\n \t * avoid false positives.\n@@ -1000,6 +1073,7 @@ enic_copy_filter(const struct rte_flow_item pattern[],\n \tenum rte_flow_item_type prev_item;\n \tconst struct enic_items *item_info;\n \tstruct copy_item_args args;\n+\tenic_copy_item_fn *copy_fn;\n \tu8 is_first_item = 1;\n \n \tFLOW_TRACE();\n@@ -1017,7 +1091,8 @@ enic_copy_filter(const struct rte_flow_item pattern[],\n \n \t\titem_info = &cap->item_info[item->type];\n \t\tif (item->type > cap->max_item_type ||\n-\t\t    item_info->copy_item == NULL) {\n+\t\t    item_info->copy_item == NULL ||\n+\t\t    (inner_ofst > 0 && item_info->inner_copy_item == NULL)) {\n \t\t\trte_flow_error_set(error, ENOTSUP,\n \t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM,\n \t\t\t\tNULL, \"Unsupported item.\");\n@@ -1029,7 +1104,9 @@ enic_copy_filter(const struct rte_flow_item pattern[],\n \t\t\tgoto stacking_error;\n \n \t\targs.item = item;\n-\t\tret = item_info->copy_item(&args);\n+\t\tcopy_fn = inner_ofst > 0 ? item_info->inner_copy_item :\n+\t\t\titem_info->copy_item;\n+\t\tret = copy_fn(&args);\n \t\tif (ret)\n \t\t\tgoto item_not_supported;\n \t\tprev_item = item->type;\n",
    "prefixes": [
        "13/15"
    ]
}