From patchwork Fri Jan 8 06:32:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 86173 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (xvm-189-124.dc0.ghst.net [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 536DEA0524; Fri, 8 Jan 2021 07:32:39 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id CE770140DFA; Fri, 8 Jan 2021 07:32:38 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id CA751140DF6 for ; Fri, 8 Jan 2021 07:32:36 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from akozyrev@nvidia.com) with SMTP; 8 Jan 2021 08:32: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 1086WZqo023082; Fri, 8 Jan 2021 08:32: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, 8 Jan 2021 06:32:34 +0000 Message-Id: <20210108063234.7679-1-akozyrev@nvidia.com> X-Mailer: git-send-email 2.24.1 MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH] ethdev: introduce generic copy rte flow action 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 Sender: "dev" Implement a generic copy flow API to allow copying of an arbitrary header field (as well as mark, metadata or tag) to another item. This generic copy mechanism removes the necessity to implement a separate RTE Flow action every time we need to modify a new packet field in the future. A user-provided value can be used from a specified tag/metadata or directly copied from other packet field. The number of bits to copy as well as the offset to start from can be specified to allow a partial copy or copy into an arbitrary place in a packet for greater flexibility. RFC: http://patches.dpdk.org/patch/85384/ Signed-off-by: Alexander Kozyrev --- doc/guides/prog_guide/rte_flow.rst | 35 ++++++++++++++++++ lib/librte_ethdev/rte_flow.c | 1 + lib/librte_ethdev/rte_flow.h | 59 ++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 86b3444803..b737ff9dad 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -2766,6 +2766,41 @@ The behaviour of the shared action defined by ``action`` argument of type | no properties | +---------------+ +Action: ``COPY_ITEM`` +^^^^^^^^^^^^^^^^^^^^^ + +Copy ``width`` bits from ``src`` item to ``dst`` item. + +An arbitrary header field (as well as mark, metadata or tag values) +can be used as both source and destination items as set by ``item``. + +Inner packet header fields can be accessed using the ``index`` and +it is possible to start the copy from the ``offset`` bits in an item. + +.. _table_rte_flow_action_copy_item: + +.. table:: COPY_ITEM + + +-----------------------------------------+ + | Field | Value | + +===============+=========================+ + | ``dst`` | destination item | + | ``src`` | source item | + | ``width`` | number of bits to copy | + +---------------+-------------------------+ + +.. _table_rte_flow_action_copy_data: + +.. table:: destination/source item definition + + +----------------------------------------------------------+ + | Field | Value | + +===============+==========================================+ + | ``item`` | ID of a packet field/mark/metadata/tag | + | ``index`` | index of outer/inner header or tag array | + | ``offset`` | number of bits to skip during the copy | + +---------------+------------------------------------------+ + Negative types ~~~~~~~~~~~~~~ diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c index a06f64c271..fdbabefc47 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_ITEM, sizeof(struct rte_flow_action_copy_item)), /** * 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..0540c861fb 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_item. + */ + RTE_FLOW_ACTION_TYPE_COPY_ITEM, }; /** @@ -2791,6 +2801,55 @@ struct rte_flow_action_set_dscp { */ struct rte_flow_shared_action; +enum rte_flow_item_id { + RTE_FLOW_ITEM_NONE = 0, + RTE_FLOW_ITEM_MAC_DST, + RTE_FLOW_ITEM_MAC_SRC, + RTE_FLOW_ITEM_VLAN_TYPE, + RTE_FLOW_ITEM_VLAN_ID, + RTE_FLOW_ITEM_MAC_TYPE, + RTE_FLOW_ITEM_IPV4_DSCP, + RTE_FLOW_ITEM_IPV4_TTL, + RTE_FLOW_ITEM_IPV4_SRC, + RTE_FLOW_ITEM_IPV4_DST, + RTE_FLOW_ITEM_IPV6_HOPLIMIT, + RTE_FLOW_ITEM_IPV6_SRC, + RTE_FLOW_ITEM_IPV6_DST, + RTE_FLOW_ITEM_TCP_PORT_SRC, + RTE_FLOW_ITEM_TCP_PORT_DST, + RTE_FLOW_ITEM_TCP_SEQ_NUM, + RTE_FLOW_ITEM_TCP_ACK_NUM, + RTE_FLOW_ITEM_TCP_FLAGS, + RTE_FLOW_ITEM_UDP_PORT_SRC, + RTE_FLOW_ITEM_UDP_PORT_DST, + RTE_FLOW_ITEM_VXLAN_VNI, + RTE_FLOW_ITEM_GENEVE_VNI, + RTE_FLOW_ITEM_GTP_TEID, + RTE_FLOW_ITEM_TAG, + RTE_FLOW_ITEM_MARK, + RTE_FLOW_ITEM_META, +}; + +struct rte_flow_action_copy_data { + enum rte_flow_item_id item; + uint32_t index; + uint32_t offset; +}; + +/** + * RTE_FLOW_ACTION_TYPE_COPY_ITEM + * + * 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_item { + struct rte_flow_action_copy_data dst; + struct rte_flow_action_copy_data src; + uint32_t width; +}; + /* Mbuf dynamic field offset for metadata. */ extern int32_t rte_flow_dynf_metadata_offs; From patchwork Tue Jan 12 05:01:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kozyrev X-Patchwork-Id: 86367 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id ED269A04B5; Tue, 12 Jan 2021 06:01:17 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id BE393140D4D; Tue, 12 Jan 2021 06:01:17 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by mails.dpdk.org (Postfix) with ESMTP id 4FBA8140D1C for ; Tue, 12 Jan 2021 06:01:16 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from akozyrev@nvidia.com) with SMTP; 12 Jan 2021 07:01:14 +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 10C51DBK004956; Tue, 12 Jan 2021 07:01:13 +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: Tue, 12 Jan 2021 05:01:10 +0000 Message-Id: <20210112050110.1987-3-akozyrev@nvidia.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20210112050110.1987-1-akozyrev@nvidia.com> References: <20210108063234.7679-1-akozyrev@nvidia.com> <20210112050110.1987-1-akozyrev@nvidia.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v2 2/2] app/testpmd: add support for generic copy rte flow action 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 Sender: "dev" Add support for the RTE_FLOW_ACTION_COPY_ITEM to the testpmd. Implement CLI to create the copy_item action and supply all the needed parameters to copy an arbitrary packet field (as well as mark, tag or metadata) into another item. Example of the flow is the following: flow create 0 egress group 1 pattern eth / ipv4 / udp / end actions copy_item dst_type tag dst_index 0 dst_offset 8 src_type gtp_teid src_index 0 src_offset 0 width 32 / end This flow copies 32 bits from the first Tag in the Tags array into the outermost GTP TEID packet header field. 8 bits of the Tag are skipped as indicated by the dst_offset action parameter. Signed-off-by: Alexander Kozyrev --- app/test-pmd/cmdline_flow.c | 156 ++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 585cab98b4..1acf8fddf8 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -408,6 +408,16 @@ enum index { ACTION_SAMPLE_INDEX_VALUE, ACTION_SHARED, SHARED_ACTION_ID2PTR, + ACTION_COPY_ITEM, + ACTION_COPY_ITEM_DST_TYPE, + ACTION_COPY_ITEM_DST_TYPE_VALUE, + ACTION_COPY_ITEM_DST_INDEX, + ACTION_COPY_ITEM_DST_OFFSET, + ACTION_COPY_ITEM_SRC_TYPE, + ACTION_COPY_ITEM_SRC_TYPE_VALUE, + ACTION_COPY_ITEM_SRC_INDEX, + ACTION_COPY_ITEM_SRC_OFFSET, + ACTION_COPY_ITEM_WIDTH, }; /** Maximum size for pattern in struct rte_flow_item_raw. */ @@ -561,6 +571,18 @@ struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM]; struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM]; struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM]; +static const char *const copy_item_table[] = { + "none", "mac_dst", "mac_src", + "vlan_type", "vlan_id", "mac_type", + "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst", + "ipv6_hoplimit", "ipv6_src", "ipv6_dst", + "tcp_port_src", "tcp_port_dst", + "tcp_seq_num", "tcp_ack_num", "tcp_flags", + "udp_port_src", "udp_port_dst", + "vxlan_vni", "geneve_vni", "gtp_teid", + "tag", "mark", "meta", NULL +}; + /** Maximum number of subsequent tokens and arguments on the stack. */ #define CTX_STACK_SIZE 16 @@ -1306,6 +1328,7 @@ static const enum index next_action[] = { ACTION_AGE, ACTION_SAMPLE, ACTION_SHARED, + ACTION_COPY_ITEM, ZERO, }; @@ -1638,6 +1661,10 @@ static int parse_vc_action_sample_index(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size); +static int +parse_vc_copy_item(struct context *ctx, const struct token *token, + const char *str, unsigned int len, void *buf, + unsigned int size); static int parse_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -1722,6 +1749,8 @@ static int comp_set_raw_index(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_set_sample_index(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_set_copy_item(struct context *, const struct token *, + unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -4037,6 +4066,85 @@ static const struct token token_list[] = { .call = parse_vc_action_raw_decap_index, .comp = comp_set_raw_index, }, + [ACTION_COPY_ITEM] = { + .name = "copy_item", + .help = "copy data from dst to src item", + .priv = PRIV_ACTION(COPY_ITEM, + sizeof(struct rte_flow_action_copy_item)), + .next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_DST_TYPE)), + .call = parse_vc, + }, + [ACTION_COPY_ITEM_DST_TYPE] = { + .name = "dst_type", + .help = "destination item type", + .next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_DST_INDEX), + NEXT_ENTRY(ACTION_COPY_ITEM_DST_TYPE_VALUE)), + .call = parse_vc_conf, + }, + [ACTION_COPY_ITEM_DST_TYPE_VALUE] = { + .name = "{type}", + .help = "destination item type value", + .call = parse_vc_copy_item, + .comp = comp_set_copy_item, + }, + [ACTION_COPY_ITEM_DST_INDEX] = { + .name = "dst_index", + .help = "destination item index", + .next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_DST_OFFSET), + NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item, + dst.index)), + .call = parse_vc_conf, + }, + [ACTION_COPY_ITEM_DST_OFFSET] = { + .name = "dst_offset", + .help = "destination item offset", + .next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_SRC_TYPE), + NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item, + dst.offset)), + .call = parse_vc_conf, + }, + [ACTION_COPY_ITEM_SRC_TYPE] = { + .name = "src_type", + .help = "source item type", + .next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_SRC_INDEX), + NEXT_ENTRY(ACTION_COPY_ITEM_SRC_TYPE_VALUE)), + .call = parse_vc_conf, + }, + [ACTION_COPY_ITEM_SRC_TYPE_VALUE] = { + .name = "{type}", + .help = "source item type value", + .call = parse_vc_copy_item, + .comp = comp_set_copy_item, + }, + [ACTION_COPY_ITEM_SRC_INDEX] = { + .name = "src_index", + .help = "source item type index", + .next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_SRC_OFFSET), + NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item, + src.index)), + .call = parse_vc_conf, + }, + [ACTION_COPY_ITEM_SRC_OFFSET] = { + .name = "src_offset", + .help = "source item type offset", + .next = NEXT(NEXT_ENTRY(ACTION_COPY_ITEM_WIDTH), + NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item, + src.offset)), + .call = parse_vc_conf, + }, + [ACTION_COPY_ITEM_WIDTH] = { + .name = "width", + .help = "number of bits to copy", + .next = NEXT(NEXT_ENTRY(ACTION_NEXT), + NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_copy_item, + width)), + .call = parse_vc_conf, + }, /* Top level command. */ [SET] = { .name = "set", @@ -5960,6 +6068,36 @@ parse_vc_action_sample_index(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for copy_item command. */ +static int +parse_vc_copy_item(struct context *ctx, const struct token *token, + const char *str, unsigned int len, void *buf, + unsigned int size) +{ + struct rte_flow_action_copy_item *action_copy_item; + unsigned int i; + + (void)token; + (void)buf; + (void)size; + if (ctx->curr != ACTION_COPY_ITEM_DST_TYPE_VALUE && + ctx->curr != ACTION_COPY_ITEM_SRC_TYPE_VALUE) + return -1; + for (i = 0; copy_item_table[i]; ++i) + if (!strcmp_partial(copy_item_table[i], str, len)) + break; + if (!copy_item_table[i]) + return -1; + if (!ctx->object) + return len; + action_copy_item = ctx->object; + if (ctx->curr == ACTION_COPY_ITEM_DST_TYPE_VALUE) + action_copy_item->dst.item = i; + else + action_copy_item->src.item = i; + return len; +} + /** Parse tokens for destroy command. */ static int parse_destroy(struct context *ctx, const struct token *token, @@ -7029,6 +7167,24 @@ comp_set_sample_index(struct context *ctx, const struct token *token, return nb; } +/** Complete item type for copy_item command. */ +static int +comp_set_copy_item(struct context *ctx, const struct token *token, + unsigned int ent, char *buf, unsigned int size) +{ + uint16_t idx = 0; + + RTE_SET_USED(ctx); + RTE_SET_USED(token); + for (idx = 0; copy_item_table[idx]; ++idx) + ; + if (!buf) + return idx + 1; + if (ent < idx) + return strlcpy(buf, copy_item_table[ent], size); + return -1; +} + /** Internal context. */ static struct context cmd_flow_context;