From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 ; 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 To: , CC: , , Ferruh Yigit , Viacheslav Ovsiienko 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: 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Demonstrate flex item API usage on known network protocols. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- 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 + + 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 + + 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 + + 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