From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id B7E78A0C4C;
	Sun, 21 Nov 2021 09:19:08 +0100 (CET)
Received: from [217.70.189.124] (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 3DBE64014E;
	Sun, 21 Nov 2021 09:19:08 +0100 (CET)
Received: from NAM02-BN1-obe.outbound.protection.outlook.com
 (mail-bn1nam07on2066.outbound.protection.outlook.com [40.107.212.66])
 by mails.dpdk.org (Postfix) with ESMTP id 5023F40143
 for <dev@dpdk.org>; Sun, 21 Nov 2021 09:19:07 +0100 (CET)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=TqD0+GmhtuXcc+pgnh92pAUyAtCh8x2eeuOl8GdKPzuo61DoynZANLhvu8osyDiRcDTfsF3fEFrmQt3H0BdBwruxGiHB5lVoKa3ue7fwFp6GCvtmF1tXT1ptHSUG614PcuqWmrMwwZyfYw8UB3LFlLnA4H+4RhAZaJ56iFrpT6bXJGQuTSIYlQRv7Q+/QUcIAqsPQJyeUYnWM95amNq9BmsKsCns5qXCrzTZfLDrCeJtS4WdEZvdXlrVodb7Oeq5tQchuMNw9MOjcuAhe50MNI3XaYg5m0VwPzVA4W15yfp0tWV0V035OtsaYq8xqkzqlJGpTMcgBxxshaItW++ezw==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; 
 s=arcselector9901;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;
 bh=lYTqce8sfFm3fM+PB99itjiBO15KFinCTqQydVeWn6U=;
 b=oah1dwDKRAdFDAx9QdcbkRMjNhE1sRovcKXnyr71vxwVGUg29KWDXJgB3I0LYuYfyoiRcx0uKIiAN0yXTE+LW2mKUatL9N4ENAnXGv8MC/V5EEFrQB9jiCwmfb0+bFJtHq/nLY+t6/0yOhkNRnWuHvPWAOzpelJpq2IcgovaCpVPomurcEBhCE7d925n+CF0077L1cP4mMVxNehs1VGzdGrgUc5iIkdfYmSNoKPfpg6d7bbCxzz3uaRpM/Egxv92EeL3kpLyD1NTxS9YYKfd/2tuSokgdE82660PprKeWPy9eag2dUU/R+3JvDaf5MOeEIAknb1yUhFeoqEAodbiWA==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is
 216.228.112.34) smtp.rcpttodomain=intel.com smtp.mailfrom=nvidia.com;
 dmarc=pass (p=quarantine sp=quarantine pct=100) action=none
 header.from=nvidia.com; dkim=none (message not signed); arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;
 s=selector2;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=lYTqce8sfFm3fM+PB99itjiBO15KFinCTqQydVeWn6U=;
 b=nQe9ZkQmUH88lcHwPHGa3NGxTYaFfrNCpbefCDdIUlEPYMnEMFgpBvxms2ERGj2IbVzmonGQJHzEWGJ7ftvd6LudrRPZd653T4UiGLZKPkNdacMEu62wx9PLeYwIglIWfaNDXCtEBTqGkJX0y8MGzwBmvqF+r+CdyD8viyjm0asGyxQrJ0Nc+bXZkZSi7Z0D1O+E4mQlSY1xA8U+rX0g3KnY5p9D9kmPfw+8zZlXysLJveiLc0jnY5u3HRIM0i3uunjw3BDnb3rSbsDE/rfIACuEwR7sVh6rVyd5dJGO7A60Iv1p9lubwWEjlTEGEeqC11CKC25paayj3+835ejljg==
Received: from MW4PR04CA0156.namprd04.prod.outlook.com (2603:10b6:303:85::11)
 by BL0PR12MB4738.namprd12.prod.outlook.com (2603:10b6:208:8e::13)
 with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.19; Sun, 21 Nov
 2021 08:19:04 +0000
Received: from CO1NAM11FT023.eop-nam11.prod.protection.outlook.com
 (2603:10b6:303:85:cafe::59) by MW4PR04CA0156.outlook.office365.com
 (2603:10b6:303:85::11) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.22 via Frontend
 Transport; Sun, 21 Nov 2021 08:19:04 +0000
X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.112.34)
 smtp.mailfrom=nvidia.com; dkim=none (message not signed)
 header.d=none;dmarc=pass action=none header.from=nvidia.com;
Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates
 216.228.112.34 as permitted sender) receiver=protection.outlook.com;
 client-ip=216.228.112.34; helo=mail.nvidia.com;
Received: from mail.nvidia.com (216.228.112.34) by
 CO1NAM11FT023.mail.protection.outlook.com (10.13.175.35) with Microsoft SMTP
 Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id
 15.20.4713.20 via Frontend Transport; Sun, 21 Nov 2021 08:19:03 +0000
Received: from nvidia.com (172.20.187.6) by HQMAIL107.nvidia.com
 (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 21 Nov
 2021 08:19:00 +0000
From: Gregory Etelson <getelson@nvidia.com>
To: <dev@dpdk.org>, <getelson@nvidia.com>
CC: <rasland@nvidia.com>, <thomas@monjalon.net>, Ferruh Yigit
 <ferruh.yigit@intel.com>, Viacheslav Ovsiienko <viacheslavo@nvidia.com>
Subject: [PATCH v2] doc: add flex item API examples
Date: Sun, 21 Nov 2021 10:18:46 +0200
Message-ID: <20211121081846.10674-1-getelson@nvidia.com>
X-Mailer: git-send-email 2.34.0
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Content-Type: text/plain
X-Originating-IP: [172.20.187.6]
X-ClientProxiedBy: HQMAIL105.nvidia.com (172.20.187.12) To
 HQMAIL107.nvidia.com (172.20.187.13)
X-EOPAttributedMessage: 0
X-MS-PublicTrafficType: Email
X-MS-Office365-Filtering-Correlation-Id: 1399ef36-b2d1-4c9b-29e2-08d9acc79474
X-MS-TrafficTypeDiagnostic: BL0PR12MB4738:
X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr
X-Microsoft-Antispam-PRVS: <BL0PR12MB4738F683FAAEC7FAC15DF21FA59E9@BL0PR12MB4738.namprd12.prod.outlook.com>
X-MS-Oob-TLC-OOBClassifiers: OLM:8882;
X-MS-Exchange-SenderADCheck: 1
X-MS-Exchange-AntiSpam-Relay: 0
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: RdpoAKyWCKfSrLIrQhZbEsSStgbAiTrc9Vcw66SWgU3G13eI+HCjmYOvzGjLhpIL+4J1/06eymle6X4W8jiEt3DQpmwS4jnZ4M2PL0OONfIXYMavb2xzrM9KskBr/OctMrk4WNQnCptYK0S750imzxM8xVRxy5s4h0zbhFktXXWrrjBZ9FR/wmXgHB8PdkNF+5szQ84JGHiLLfIIxblKoYCN2nkyT1j3GIRmSkYSyeOu0rqV+BHSMRekdrhOpmet3LlDi7lPOU/JXICJzFpPFZ4cdk+Jon+R296a2dNx9YNSa33EBtDmdJKy8SzsTdkwoBtmdTA7qAfjUlE5I1k/NlVF38z34PRG7FqvP8pJaAj6GZw3avHw4sZbj08dCOEPOGkcx6Jd0Zie5YZUPNV2dt4rTaCzpmOoBn1pPnuZlI3HhowQIM8xmt88Q+kiH8jILpe1ktdPM2kXewi7ebvvnoxeZQqiX2RGKZSGCZoMjCuYhCNJ10BahsY5ZfUd2bflYkz8NO2Nrl2nsleCF5QFjA/nxAO0waRK9ZlvOqJRka9ozQcRNHszbNKwY+K2eqav1qr5cZoLckBjv7R9jM7tcoHaztdy9+vsvxLW2c7yd0B+JBipGMMJkWkWzEmg98WNX77unoqZfNWUwY5huscs9hQCwJwiYt27JfGLsBM05OOHqCHBqJAaNjA4kAU/YItqUHaCg0KA+CvQLNdwzYopVQ==
X-Forefront-Antispam-Report: CIP:216.228.112.34; CTRY:US; LANG:en; SCL:1; SRV:;
 IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:schybrid03.nvidia.com; CAT:NONE;
 SFS:(4636009)(36840700001)(46966006)(36860700001)(26005)(5660300002)(2616005)(86362001)(336012)(55016002)(16526019)(186003)(7696005)(30864003)(508600001)(82310400003)(426003)(47076005)(7636003)(356005)(7049001)(6666004)(36906005)(1076003)(110136005)(70586007)(36756003)(70206006)(54906003)(2906002)(8676002)(4326008)(107886003)(83380400001)(6286002)(8936002)(316002);
 DIR:OUT; SFP:1101; 
X-OriginatorOrg: Nvidia.com
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Nov 2021 08:19:03.7566 (UTC)
X-MS-Exchange-CrossTenant-Network-Message-Id: 1399ef36-b2d1-4c9b-29e2-08d9acc79474
X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a
X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.112.34];
 Helo=[mail.nvidia.com]
X-MS-Exchange-CrossTenant-AuthSource: CO1NAM11FT023.eop-nam11.prod.protection.outlook.com
X-MS-Exchange-CrossTenant-AuthAs: Anonymous
X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem
X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL0PR12MB4738
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>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

Demonstrate flex item API usage on known network protocols.

Signed-off-by: Gregory Etelson <getelson@nvidia.com>
Reviewed-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
v2: Fix spelling error.
---
 doc/guides/howto/flex_item.rst | 618 +++++++++++++++++++++++++++++++++
 doc/guides/howto/index.rst     |   1 +
 2 files changed, 619 insertions(+)
 create mode 100644 doc/guides/howto/flex_item.rst

diff --git a/doc/guides/howto/flex_item.rst b/doc/guides/howto/flex_item.rst
new file mode 100644
index 0000000000..db828e3dc8
--- /dev/null
+++ b/doc/guides/howto/flex_item.rst
@@ -0,0 +1,618 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+   Copyright (c) 2021 NVIDIA Corporation & Affiliates
+
+
+Flex item API - examples
+========================
+
+The document uses known network protocols to demonstrate flex item API
+programming examples.
+
+eCPRI protocol
+--------------
+
+This example demonstrates basic flex item API usage.
+
+Header structure
+~~~~~~~~~~~~~~~~
+
+::
+
+   0    1    2    3    4    5    6    7
+   +----+----+----+----+----+----+----+----+
+   |  protocol version | reserved     | C  | +0
+   +----+----+----+----+----+----+----+----+
+   |          message type                 | +1
+   +----+----+----+----+----+----+----+----+
+   |                                       | +2
+   +----      payload size             ----+
+   |                                       | +3
+   +----+----+----+----+----+----+----+----+
+
+Flex item configuration
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+   :linenos:
+
+   #include <rte_flow.h>
+
+   const struct rte_flow_item_flex_conf ecpri_flex_conf = {
+      /* single eCPRI header in a packet. Can be ether inner or outer */
+      .tunnel = FLEX_TUNNEL_MODE_SINGLE,
+
+      /* eCPRI header size description */
+      .next_header = {
+         .field_mode = FIELD_MODE_FIXED,  /* fixed-size header */
+         .field_size = 4 * sizeof(char) * CHAR_BIT;
+      },
+
+      /* eCPRI header is followed by a payload */
+      .next_protocol = {},
+
+      /* single sample that covers entire eCPRI header */
+      .sample_data = {
+         {
+            .field_mode = FIELD_MODE_FIXED,
+            .field_size = 4 * sizeof(char) * CHAR_BIT,
+            .field_base = 0
+         }
+      },
+      .nb_samples = 1,
+
+      /* eCPRI protocol follows ether Ethernet or UDP headers */
+      .input_link = {
+         {
+            .item = {
+               .type = RTE_FLOW_ITEM_TYPE_ETH,
+               .spec = &(struct rte_flow_item_eth) {
+                  .type = rte_cpu_to_be_16(0xAEFE),
+               },
+            }
+         },
+         {
+            .item = {
+               .type = RTE_FLOW_ITEM_TYPE_UDP,
+               .spec = &(struct rte_flow_item_udp) {
+                  .hdr.dst_port = rte_cpu_to_be_16(0xAEFE)
+               },
+            }
+         },
+      },
+      .nb_inputs = 2,
+
+      /* no network protocol follows eCPRI header */
+      .nb_outputs = 0;
+   };
+
+   struct rte_flow_item_flex_handle *ecpri_flex_handle;
+   ecpri_flex_handle = rte_flow_flex_item_create(port_id, ecpri_flex_conf, error);
+
+Flex flow item
+~~~~~~~~~~~~~~
+
+Application defined structure to match eCPRI header:
+
+.. code-block:: c
+   :linenos:
+
+   struct ecpri_hdr {
+      unsigned char version:4;
+      unsigned char reserved:3;
+      unsigned char c:1;
+      unsigned char msg_type;
+      unsigned short payload_size;
+   } __rte_packed;
+
+
+* Match all but last eCPRI PDUs:
+
+   .. code-block:: c
+      :linenos:
+
+      const struct ecpri_hdr ecpri_not_last_spec = {
+         .version = 1,
+         .c = 1
+      };
+      const struct ecpri_hdr ecpri_not_last_mask = {
+         .version = 0xf,
+         .c = 1
+      };
+
+      const struct rte_flow_item_flex ecpri_not_last_flex_spec = {
+         .handle = ecpri_flex_handle,
+         .length = sizeof(ecpri_not_last_spec),
+         .pattern = &ecpri_not_last_spec
+      };
+
+      const struct rte_flow_item_flex ecpri_not_last_flex_mask = {
+         .handle = ecpri_flex_handle,
+         .length = sizeof(ecpri_not_last_mask),
+         .pattern = &ecpri_not_last_mask
+      };
+
+      const struct rte_flow_item ecpri_not_last_flow_item = {
+         .type = RTE_FLOW_ITEM_TYPE_FLEX,
+         .spec = (const void *)&ecpri_not_last_flex_spec,
+         .mask = (const void *)&ecpri_not_last_flex_mask,
+      };
+
+* Match ``Generic Data Transfer`` type eCPRI PDUs:
+
+   .. code-block:: c
+      :linenos:
+
+      const struct ecpri_hdr ecpri_data_transfer_spec = {
+         .version = 1,
+         .msg_type = 3
+      };
+      const struct ecpri_hdr ecpri_data_transfer_mask = {
+         .version = 0xf,
+         .msg_type = 0xff
+      };
+
+      const struct rte_flow_item_flex ecpri_data_transfer_flex_spec = {
+         .handle = ecpri_flex_handle,
+         .length = sizeof(ecpri_data_transfer_spec),
+         .pattern = &ecpri_data_transfer_spec
+      };
+
+      const struct rte_flow_item_flex ecpri_data_transfer_flex_mask = {
+         .handle = ecpri_flex_handle,
+         .length = sizeof(ecpri_data_transfer_mask),
+         .pattern = &ecpri_data_transfer_mask
+      };
+
+      const struct rte_flow_item ecpri_data_transfer_flow_item = {
+         .type = RTE_FLOW_ITEM_TYPE_FLEX,
+         .spec = (const void *)&ecpri_data_transfer_flex_spec,
+         .mask = (const void *)&ecpri_data_transfer_flex_mask,
+      };
+
+Geneve protocol
+---------------
+
+Demonstrate flex item API usage with variable length network header.
+Protocol header is built from a fixed size section that is followed by
+variable size section.
+
+
+Header Structure
+~~~~~~~~~~~~~~~~
+
+Geneve header format:
+
+::
+
+                       1                   2                   3
+   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |Ver|  Opt Len  |O|C|    Rsvd.  |          Protocol Type        |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |        Virtual Network Identifier (VNI)       |    Reserved   |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                                                               |
+   ~                    Variable-Length Options                    ~
+   |                                                               |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+Geneve option format:
+
+::
+
+   0                   1                   2                   3
+   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |          Option Class         |      Type     |R|R|R| Length  |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                                                               |
+   ~                  Variable-Length Option Data                  ~
+   |                                                               |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+Flex item configuration
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+   :linenos:
+
+   #include <rte_flow.h>
+
+   const struct rte_flow_item_flex_conf geneve_flex_conf = {
+      /* Geneve is tunnel protocol */
+      .tunnel = FLEX_TUNNEL_MODE_TUNNEL,
+
+      /*
+       * Geneve header size description
+       * Header size calculation: field_size + ([Length] & offset_mask) << offset_shift
+       */
+      .next_header = {
+         .field_mode = FIELD_MODE_OFFSET,           /* variable header length */
+         .field_size = 2 * sizeof(int) * CHAR_BIT,  /* minimal header size */
+         .offset_base = 2,                          /* length extension location in the header */
+         .offset_mask = 0x3f,                       /* length extension mask */
+         .offset_shift = 3,                         /* length extension scale factor */
+      },
+
+      /* next protocol location in Geneve header */
+      .next_protocol = {
+         .field_base = 16,
+         .field_size = 16,
+      },
+
+      /* Samples for flow matches */
+      .sample_data = {
+         /* sample first 2 double words */
+         {
+            .field_mode = FIELD_MODE_FIXED,
+            .field_size = 64,
+            .field_base = 0,
+         },
+         /* sample 6 optional double words */
+         {
+            .field_mode = FIELD_MODE_FIXED,
+            .field_size = 192,
+            .field_base = 64,
+         },
+      },
+      .nb_samples = 2,
+
+      /* Geneve follows UDP header */
+      .input_link = {
+         {
+            .item = {
+               .type = RTE_FLOW_ITEM_TYPE_UDP,
+               .spec = &(struct rte_flow_item_udp) {
+                  .hdr.dst_port = rte_cpu_to_be_16(6081)
+               }
+            }
+         }
+      },
+      .nb_inputs = 1,
+
+      .output_link = {
+         {
+            .item = { .type = RTE_FLOW_ITEM_TYPE_ETH },
+            .next = rte_cpu_to_be_16(0x6558)
+         },
+         {
+            .item = { .type = RTE_FLOW_ITEM_TYPE_IPv4 },
+            .next = rte_cpu_to_be_16(0x0800)
+         },
+         {
+            .item = { .type = RTE_FLOW_ITEM_TYPE_IPv6 },
+            .next = rte_cpu_to_be_16(0x86dd)
+         },
+      },
+      .nb_output = 3
+   };
+
+   struct rte_flow_item_flex_handle *geneve_flex_handle;
+   geneve_flex_handle = rte_flow_flex_item_create(port_id, geneve_flex_conf, error);
+
+Flex flow item
+~~~~~~~~~~~~~~
+
+Application defined structure for Geneve header:
+
+.. code-block:: c
+   :linenos:
+
+   struct geneve_hdr {
+      unsigned int ver:2;
+      unsigned int opt_len:6;
+      unsigned int o:1;
+      unsigned int c:1;
+      unsigned int reserved1:6;
+      unsigned int next_protocol:16;
+      unsigned int vni:24;
+      unsigned int reserved2:8;
+      unsigned long options[];
+   } __rte_packed;
+
+   struct geneve_option_hdr {
+      unsigned int class:16;
+      unsigned int type:8;
+      unsigned int flags:3;
+      unsigned int length:5;
+      unsigned int data[];
+   } __rte_packed;
+
+* Match Geneve basic header
+
+   .. code-block:: c
+      :linenos:
+
+      const struct geneve_hdr geneve_basic_header_spec = {
+         .ver = 0,
+         .opt_len = 0,
+      };
+      const struct geneve_hdr geneve_basic_header_mask = {
+         .ver = 3,
+         .opt_len = 0x3f,
+      };
+
+      const struct rte_flow_item_flex geneve_basic_header_flex_spec = {
+         .handle = geneve_flex_handle,
+         .length = sizeof(geneve_basic_header_spec),
+         .pattern = &geneve_basic_header_spec
+      };
+
+      const struct rte_flow_item_flex geneve_basic_header_flex_mask = {
+         .handle = geneve_flex_handle,
+         .length = sizeof(geneve_basic_header_mask),
+         .pattern = &geneve_basic_header_mask
+      };
+
+      const struct rte_flow_item geneve_basic_header_flow_item = {
+         .type = RTE_FLOW_ITEM_TYPE_FLEX,
+         .spec = (const void *)&geneve_basic_header_flex_spec,
+         .mask = (const void *)&geneve_basic_header_flex_mask,
+      };
+
+* Match if the first option class is Open vSwitch
+
+   .. code-block:: c
+      :linenos:
+
+      const struct geneve_option_hdr geneve_ovs_opt_spec = {
+         .class = rte_cpu_to_be16(0x0101),
+      };
+
+      const struct geneve_option_hdr geneve_ovs_opt_mask = {
+         .class = 0xffff,
+      };
+
+      const struct geneve_hdr geneve_hdr_with_ovs_spec = {
+         .ver = 0,
+         .options = (const unsigned long *)&geneve_ovs_opt_spec
+      };
+
+      const struct geneve_hdr geneve_hdr_with_ovs_mask = {
+         .ver = 3,
+         .options = (const unsigned long *)&geneve_ovs_opt_mask
+      };
+
+      const struct rte_flow_item_flex geneve_flex_spec = {
+         .handle = geneve_flex_handle,
+         .length = sizeof(geneve_hdr_with_ovs_spec) + sizeof(geneve_ovs_opt_spec),
+         .pattern = &geneve_hdr_with_ovs_spec
+      };
+
+      const struct rte_flow_item_flex geneve_flex_mask = {
+         .handle = geneve_flex_handle,
+         .length = sizeof(geneve_hdr_with_ovs_mask) + sizeof(geneve_ovs_opt_mask),
+         .pattern = &geneve_hdr_with_ovs_mask
+      };
+
+      const struct rte_flow_item geneve_vni_flow_item = {
+         .type = RTE_FLOW_ITEM_TYPE_FLEX,
+         .spec = (const void *)&geneve_flex_spec,
+         .mask = (const void *)&geneve_flex_mask,
+      };
+
+Extended GRE packet header (RFC 2890)
+-------------------------------------
+
+This example shows how to configure flex item if protocol header length
+depends on a bitmask.
+
+Header structure
+~~~~~~~~~~~~~~~~
+
+::
+
+                        1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |C| |K|S| Reserved0       | Ver |         Protocol Type         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |      Checksum (optional)      |       Reserved1 (Optional)    |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                         Key (optional)                        |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                 Sequence Number (Optional)                    |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+Flex item configuration
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: c
+   :linenos:
+
+   #include <rte_flow.h>
+
+   const struct rte_flow_item_flex_conf egre_flex_conf = {
+      /* eGRE is tunnel protocol */
+      .tunnel = FLEX_TUNNEL_MODE_TUNNEL,
+
+      /*
+       * Header size description.
+       * Header calculation field_size + (bitcount([C|K|S]) & offset_mask) << offset_shift
+       */
+      .next_header = {
+         .field_mode = FIELD_MODE_BITMASK,
+         .field_size = sizeof(int) * CHAR_BIT,
+         .offset_base = 0,
+         .offset_mask = 3,
+         .offset_shift = 2
+      },
+
+      /*
+       * Samples for flow match.
+       * Adjust samples for maximal header length.
+       */
+      .sample_data = {
+         {
+            .field_mode = FIELD_MODE_FIXED,
+            .filed_size = 4 * sizeof(int) * CHAR_BIT,
+            .field_base = 0
+         }
+      }
+      .nb_samples = 1,
+
+      /* eGRE follows IPv4 or IPv6 */
+      .input_link = {
+         {
+            .item = {
+               .type = RTE_FLOW_ITEM_TYPE_IPV4,
+               .spec = &(struct rte_flow_item_ipv4) {
+                  .hdr.next_proto_id = 47
+               }
+            }
+         },
+         {
+            .item = {
+               .type = RTE_FLOW_ITEM_TYPE_IPV6,
+               .spec = &(struct rte_flow_item_ipv6) {
+                  .hdr.proto = 47
+               }
+            }
+         }
+      },
+      .nb_inputs = 2,
+
+      .output_link = {
+         {
+            .item = { .type = RTE_FLOW_ITEM_TYPE_ETH },
+            .next = rte_cpu_to_be_16(0x6558)
+         },
+         {
+            .item = { .type = RTE_FLOW_ITEM_TYPE_IPv4 },
+            .next = rte_cpu_to_be_16(0x0800)
+         },
+         {
+            .item = { .type = RTE_FLOW_ITEM_TYPE_IPv6 },
+            .next = rte_cpu_to_be_16(0x86dd)
+         },
+      },
+      .nb_output = 3
+   };
+
+   struct rte_flow_item_flex_handle *egre_flex_handle;
+   egre_flex_handle = rte_flow_flex_item_create(port_id, egre_flex_conf, error);
+
+Flex flow item
+~~~~~~~~~~~~~~
+
+Application defined eGRE header structure:
+
+.. code-block:: c
+   :linenos:
+
+   struct egre_hdr {
+      unsigned int c:1;
+      unsigned int reserved_bit:1;
+      unsigned int k:1;
+      unsigned int s:1;
+      unsigned int reserved0:9;
+      unsigned int ver:3;
+      unsigned int protocol:16;
+      unsigned int optional_cks[];
+   };
+
+* Match eGRE header
+
+.. code-block:: c
+   :linenos:
+
+   const struct egre_hdr egre_hdr_spec = {
+      .version = 0
+   };
+
+   const struct egre_hdr egre_hdr_mask = {
+      .version = 7
+   };
+
+   const struct rte_flow_item_flex egre_flex_item_spec = {
+         .handle = egre_flex_handle,
+         .length = sizeof(egre_hdr_spec),
+         .pattern = &egre_hdr_spec
+   };
+
+   const struct rte_flow_item_flex egre_flex_item_mask = {
+         .handle = egre_flex_handle,
+         .length = sizeof(egre_hdr_mask),
+         .pattern = &egre_hdr_mask
+   };
+
+   const struct rte_flow_item egre_item_spec = {
+      .type = RTE_FLOW_ITEM_TYPE_FLEX,
+      .spec = (const void *)&egre_flex_item_spec,
+      .mask = (const void *)&egre_flex_item_mask
+   };
+
+* Match key value
+
+That example needs 2 flow rules - one flow rule to match eGRE header with both
+C and K flags on and the second flow rule to match eGRE header with K flag only.
+
+.. code-block:: c
+   :linenos:
+
+   unsigned int key_val;
+
+   /* eGRE header with both C and K flags set */
+   const struct egre_hdr_ck_spec = {
+      .c = 1,
+      .k = 1,
+      .version = 0,
+      .optional_cks[1] = ky_val;
+   };
+
+   const struct egre_hdr_ck_mask = {
+      .c = 1,
+      .k = 1,
+      .version = 7,
+      .optional_cks[1] = 0xffffffff;
+   };
+
+   /* eGRE header with K flag set only */
+   const struct egre_hdr_k_spec = {
+      .k = 1,
+      .version = 0,
+      .optional_cks[0] = ky_val;
+   };
+
+   const struct egre_hdr_k_mask = {
+      .k = 1,
+      .version = 7,
+      .optional_cks[0] = 0xffffffff;
+   };
+
+   const struct rte_flow_item_flex egre_ck_flex_item_spec = {
+         .handle = egre_hdr_ck_spec,
+         .length = sizeof(egre_hdr_ck_spec) + 2 * sizeof(int),
+         .pattern = &egre_hdr_ck_spec
+   };
+
+   const struct rte_flow_item_flex egre_ck_flex_item_mask = {
+         .handle = egre_hdr_ck_spec,
+         .length = sizeof(egre_hdr_ck_spec) + 2 * sizeof(int),
+         .pattern = &egre_hdr_ck_mask
+   };
+
+   const struct rte_flow_item_flex egre_k_flex_item_spec = {
+         .handle = egre_hdr_k_spec,
+         .length = sizeof(egre_hdr_k_spec) + sizeof(int),
+         .pattern = &egre_hdr_k_spec
+   };
+
+   const struct rte_flow_item_flex egre_k_flex_item_mask = {
+         .handle = egre_hdr_k_spec,
+         .length = sizeof(egre_hdr_k_spec) + sizeof(int),
+         .pattern = &egre_hdr_k_mask
+   };
+
+   const struct rte_flow_item egre_ck_item_spec = {
+      .type = RTE_FLOW_ITEM_TYPE_FLEX,
+      .spec = (const void *)&egre_ck_flex_item_spec,
+      .mask = (const void *)&egre_ck_flex_item_mask
+   };
+
+   const struct rte_flow_item egre_k_item_spec = {
+      .type = RTE_FLOW_ITEM_TYPE_FLEX,
+      .spec = (const void *)&egre_k_flex_item_spec,
+      .mask = (const void *)&egre_k_flex_item_mask
+   };
diff --git a/doc/guides/howto/index.rst b/doc/guides/howto/index.rst
index c2a2c60ddb..7232f4d504 100644
--- a/doc/guides/howto/index.rst
+++ b/doc/guides/howto/index.rst
@@ -21,3 +21,4 @@ HowTo Guides
     debug_troubleshoot
     openwrt
     avx512
+    flex_item
-- 
2.34.0