From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 78192A09F6; Fri, 18 Dec 2020 02:31:43 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id C8F2BCA39; Fri, 18 Dec 2020 02:31:41 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id 1DE46CA38 for ; Fri, 18 Dec 2020 02:31:40 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from akozyrev@nvidia.com) with SMTP; 18 Dec 2020 03:31:35 +0200 Received: from nvidia.com (pegasus02.mtr.labs.mlnx [10.210.16.122]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 0BI1VYxA027710; Fri, 18 Dec 2020 03:31:35 +0200 From: Alexander Kozyrev To: dev@dpdk.org Cc: viacheslavo@nvidia.com, orika@nvidia.com, thomas@monjalon.net, ferruh.yigit@intel.com, andrew.rybchenko@oktetlabs.ru Date: Fri, 18 Dec 2020 01:31:29 +0000 Message-Id: <20201218013129.25186-1-akozyrev@nvidia.com> X-Mailer: git-send-email 2.24.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [RFC] ethdev: introduce copy_field rte flow action X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" RTE Flows API lacks the ability to save an arbitrary header field in order to use it later for advanced packet manipulations. Examples include the usage of VxLAN ID after the packet is decapsulated or storing this ID inside the packet payload itself or swapping an arbitrary inner and outer packet fields. The idea is to allow a copy of a specified number of bits form any packet header field into another header field: RTE_FLOW_ACTION_TYPE_COPY_FIELD with the structure defined below. struct rte_flow_action_copy_field { struct rte_flow_action_copy_data dest; struct rte_flow_action_copy_data src; uint16_t width; }; Arbitrary header field (as well as mark, metadata or tag values) can be used as both source and destination fields. This way we can save an arbitrary header field by copying its value to a tag/mark/metadata or copy it into another header field directly. tag/mark/metadata can also be used as a value to be stored in an arbitrary packet header field. struct rte_flow_action_copy_data { enum rte_flow_field_id field; uint16_t index; uint16_t offset; }; The rte_flow_field_id specifies the particular packet field (or tag/mark/metadata) to be used as a copy source or destination. The index gives access to inner packet headers or elements in the tags array. The offset allows to copy a packet field value into the payload. It is proposed to implement the "set copy_field" command to store all the required parameters and then to use this template by specifying the index of the needed copy action. For example, to modify the GTP tunnel ID after the packet is encapsulated following testpmd rules are used: set copy_field width 32 src field tag index 1 offset 0 dst field teid index 0 offset 0 flow create 0 ingress pattern ... / end raw_decap index 1 / raw_encap index 2 / copy_field index 1 / end A more generic mechanism to overwrite an arbitrary header field may be introduced to the RTE flows implementation later: RTE_FLOW_ACTION_TYPE_SET_FIELD with the structure defined below. struct rte_flow_action_copy_field { struct rte_flow_action_copy_data dest; uint8_t *data; uint16_t width; }; This way we can have the generic way to specify an immediate value and use it as data for any packet header field instead of having separate RTE Flow action for each of the packet fields. Deprecation notice may be issued to RTE_FLOW_ACTION_TYPE_SET_XXX actions after the unified method of setting a value to any packet field is implemented. Signed-off-by: Alexander Kozyrev --- lib/librte_ethdev/rte_flow.c | 1 + lib/librte_ethdev/rte_flow.h | 59 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c index a06f64c271..c3154a29e2 100644 --- a/lib/librte_ethdev/rte_flow.c +++ b/lib/librte_ethdev/rte_flow.c @@ -176,6 +176,7 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = { MK_FLOW_ACTION(SET_IPV6_DSCP, sizeof(struct rte_flow_action_set_dscp)), MK_FLOW_ACTION(AGE, sizeof(struct rte_flow_action_age)), MK_FLOW_ACTION(SAMPLE, sizeof(struct rte_flow_action_sample)), + MK_FLOW_ACTION(COPY_FIELD, sizeof(struct rte_flow_action_copy_field)), /** * Shared action represented as handle of type * (struct rte_flow_shared action *) stored in conf field (see diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h index 0977a78270..8f1798487c 100644 --- a/lib/librte_ethdev/rte_flow.h +++ b/lib/librte_ethdev/rte_flow.h @@ -2198,6 +2198,16 @@ enum rte_flow_action_type { * struct rte_flow_shared_action). */ RTE_FLOW_ACTION_TYPE_SHARED, + + /** + * Copy a packet header field, tag, mark or metadata. + * + * Allow saving an arbitrary header field by copying its value + * to a tag/mark/metadata or copy it into another header field. + * + * See struct rte_flow_action_copy_field. + */ + RTE_FLOW_ACTION_TYPE_COPY_FIELD, }; /** @@ -2791,6 +2801,55 @@ struct rte_flow_action_set_dscp { */ struct rte_flow_shared_action; +enum rte_flow_field_id { + RTE_FLOW_FIELD_NONE = 0, + RTE_FLOW_FIELD_MAC_DST, + RTE_FLOW_FIELD_MAC_SRC, + RTE_FLOW_FIELD_VLAN_TYPE, + RTE_FLOW_FIELD_VLAN_ID, + RTE_FLOW_FIELD_MAC_TYPE, + RTE_FLOW_FIELD_IPV4_DSCP, + RTE_FLOW_FIELD_IPV4_TTL, + RTE_FLOW_FIELD_IPV4_SRC, + RTE_FLOW_FIELD_IPV4_DST, + RTE_FLOW_FIELD_IPV6_HOPLIMIT, + RTE_FLOW_FIELD_IPV6_SRC, + RTE_FLOW_FIELD_IPV6_DST, + RTE_FLOW_FIELD_TCP_PORT_SRC, + RTE_FLOW_FIELD_TCP_PORT_DST, + RTE_FLOW_FIELD_TCP_SEQ_NUM, + RTE_FLOW_FIELD_TCP_ACK_NUM, + RTE_FLOW_FIELD_TCP_FLAGS, + RTE_FLOW_FIELD_UDP_PORT_SRC, + RTE_FLOW_FIELD_UDP_PORT_DST, + RTE_FLOW_FIELD_VXLAN_VNI, + RTE_FLOW_FIELD_GENEVE_VNI, + RTE_FLOW_FIELD_GTP_TEID, + RTE_FLOW_FIELD_TAG, + RTE_FLOW_FIELD_MARK, + RTE_FLOW_FIELD_META, +}; + +struct rte_flow_action_copy_data { + enum rte_flow_field_id field; + uint16_t index; + uint16_t offset; +}; + +/** + * RTE_FLOW_ACTION_TYPE_COPY_FIELD + * + * Copies a specified number of bits from a source header field + * to a destination header field. Tag, mark or metadata can also + * be used as a source/destination to allow saving/overwriting + * an arbituary header field with a user-specified value. + */ +struct rte_flow_action_copy_field { + struct rte_flow_action_copy_data dest; + struct rte_flow_action_copy_data src; + uint16_t width; +}; + /* Mbuf dynamic field offset for metadata. */ extern int32_t rte_flow_dynf_metadata_offs; -- 2.24.1