Happy New Year Gentlemen, would you mind to share your thought on the proposed 
changes?
I was thinking about renaming it to more general "copy item" to cover all 
packet fields, tags  and metadata.
Other than that it is ready for a formal patch integration in my opinion if 
there are no objections. Please advise.

Regards,
Alex

> -----Original Message-----
> From: dev <dev-boun...@dpdk.org> On Behalf Of Alexander Kozyrev
> Sent: Thursday, December 17, 2020 20:31
> To: dev@dpdk.org
> Cc: Slava Ovsiienko <viachesl...@nvidia.com>; Ori Kam <or...@nvidia.com>;
> NBU-Contact-Thomas Monjalon <tho...@monjalon.net>;
> ferruh.yi...@intel.com; andrew.rybche...@oktetlabs.ru
> Subject: [dpdk-dev] [RFC] ethdev: introduce copy_field rte flow action
> 
> 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 <akozy...@nvidia.com>
> ---
>  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

Reply via email to