get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/87390/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 87390,
    "url": "https://patches.dpdk.org/api/patches/87390/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210127024852.819-1-akozyrev@nvidia.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210127024852.819-1-akozyrev@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210127024852.819-1-akozyrev@nvidia.com",
    "date": "2021-01-27T02:48:52",
    "name": "net/mlx5: support modify field rte flow action",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "b19c726576d104ca3cf62a149679edeba9cbccc8",
    "submitter": {
        "id": 1873,
        "url": "https://patches.dpdk.org/api/people/1873/?format=api",
        "name": "Alexander Kozyrev",
        "email": "akozyrev@nvidia.com"
    },
    "delegate": {
        "id": 3268,
        "url": "https://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210127024852.819-1-akozyrev@nvidia.com/mbox/",
    "series": [
        {
            "id": 14966,
            "url": "https://patches.dpdk.org/api/series/14966/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=14966",
            "date": "2021-01-27T02:48:52",
            "name": "net/mlx5: support modify field rte flow action",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/14966/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/87390/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/87390/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "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])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 2A202A052A;\n\tWed, 27 Jan 2021 03:49:01 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 96382140DA3;\n\tWed, 27 Jan 2021 03:49:00 +0100 (CET)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by mails.dpdk.org (Postfix) with ESMTP id 85022140DA2\n for <dev@dpdk.org>; Wed, 27 Jan 2021 03:48:58 +0100 (CET)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n akozyrev@nvidia.com) with SMTP; 27 Jan 2021 04:48:55 +0200",
            "from nvidia.com (pegasus02.mtr.labs.mlnx [10.210.16.122])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10R2mtKG015775;\n Wed, 27 Jan 2021 04:48:55 +0200"
        ],
        "From": "Alexander Kozyrev <akozyrev@nvidia.com>",
        "To": "dev@dpdk.org",
        "Cc": "rasland@nvidia.com, viacheslavo@nvidia.com, matan@nvidia.com,\n orika@nvidia.com",
        "Date": "Wed, 27 Jan 2021 02:48:52 +0000",
        "Message-Id": "<20210127024852.819-1-akozyrev@nvidia.com>",
        "X-Mailer": "git-send-email 2.24.1",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH] net/mlx5: support modify field rte flow action",
        "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>,\n <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>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add support for new MODIFY_FIELD action to the Mellanox PMD.\nThis is the generic API that allows to manipulate any packet\nheader field by copying data from another packet field or\nmark, metadata, tag, or immediate value (or pointer to it).\n\nSince the API is generic and covers a lot of action under its\numbrella it makes sense to implement all the mechanics gradually\nin order to move to this API for any packet field manipulations\nin the future. This is first step of RTE flows consolidation.\n\nThe modify field RTE flow supports three operations: set, add\nand sub. This patch brings to live only the \"set\" operation.\nSupport is provided for any packet header field as well as\nmeta/tag/mark and immediate value can be used as a source.\n\nThere are few limitations for this first version of API support:\n- encapsulation levels are not supported, just outermost header\ncan be manipulated for now.\n- offsets can only be 4-bytes aligned: 32, 64 and 96 for IPv6.\n- the special ITEM_START ID is not supported as we do not allow\nto cross packet header field boundaries yet.\n\nSigned-off-by: Alexander Kozyrev <akozyrev@nvidia.com>\n---\n drivers/net/mlx5/mlx5_flow.h    |   4 +-\n drivers/net/mlx5/mlx5_flow_dv.c | 507 +++++++++++++++++++++++++++++++-\n 2 files changed, 508 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 2178a04e3a..6f6828c6a1 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -219,6 +219,7 @@ enum mlx5_feature_name {\n #define MLX5_FLOW_ACTION_SAMPLE (1ull << 36)\n #define MLX5_FLOW_ACTION_TUNNEL_SET (1ull << 37)\n #define MLX5_FLOW_ACTION_TUNNEL_MATCH (1ull << 38)\n+#define MLX5_FLOW_ACTION_MODIFY_FIELD (1ull << 39)\n \n #define MLX5_FLOW_FATE_ACTIONS \\\n \t(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | \\\n@@ -249,7 +250,8 @@ enum mlx5_feature_name {\n \t\t\t\t      MLX5_FLOW_ACTION_MARK_EXT | \\\n \t\t\t\t      MLX5_FLOW_ACTION_SET_META | \\\n \t\t\t\t      MLX5_FLOW_ACTION_SET_IPV4_DSCP | \\\n-\t\t\t\t      MLX5_FLOW_ACTION_SET_IPV6_DSCP)\n+\t\t\t\t      MLX5_FLOW_ACTION_SET_IPV6_DSCP | \\\n+\t\t\t\t      MLX5_FLOW_ACTION_MODIFY_FIELD)\n \n #define MLX5_FLOW_VLAN_ACTIONS (MLX5_FLOW_ACTION_OF_POP_VLAN | \\\n \t\t\t\tMLX5_FLOW_ACTION_OF_PUSH_VLAN)\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 1a0c0be680..d842dc9887 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -209,6 +209,8 @@ rte_col_2_mlx5_col(enum rte_color rcol)\n \treturn MLX5_FLOW_COLOR_UNDEFINED;\n }\n \n+#define MLX5DV_FLOW_MAX_MOD_FIELDS 5\n+\n struct field_modify_info {\n \tuint32_t size; /* Size of field in protocol header, in bytes. */\n \tuint32_t offset; /* Offset of field in protocol header, in bytes. */\n@@ -431,6 +433,9 @@ flow_dv_convert_modify_action(struct rte_flow_item *item,\n \t\t\t\t(int)dcopy->offset < 0 ? off_b : dcopy->offset;\n \t\t\t/* Convert entire record to big-endian format. */\n \t\t\tactions[i].data1 = rte_cpu_to_be_32(actions[i].data1);\n+\t\t\t++dcopy;\n+\t\t\tif (!dcopy)\n+\t\t\t\tbreak;\n \t\t} else {\n \t\t\tMLX5_ASSERT(item->spec);\n \t\t\tdata = flow_dv_fetch_field((const uint8_t *)item->spec +\n@@ -1324,6 +1329,339 @@ flow_dv_convert_action_modify_ipv6_dscp\n \t\t\t\t\t     MLX5_MODIFICATION_TYPE_SET, error);\n }\n \n+static void\n+mlx5_flow_field_id_to_modify_info\n+\t\t(const struct rte_flow_action_modify_data *data,\n+\t\t struct field_modify_info *info,\n+\t\t uint32_t *mask, uint32_t *value,\n+\t\t struct rte_eth_dev *dev,\n+\t\t const struct rte_flow_attr *attr,\n+\t\t struct rte_flow_error *error)\n+{\n+\tuint32_t idx = 0;\n+\tswitch (data->field) {\n+\tcase RTE_FLOW_FIELD_START:\n+\t\t/* not supported yet */\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_MAC_DST:\n+\t\tif (mask) {\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DMAC_47_16};\n+\t\t\tmask[idx] = (data->offset == 32) ? 0x0 : 0xffffffff;\n+\t\t\t++idx;\n+\t\t\tinfo[idx] = (struct field_modify_info){2, 4,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DMAC_15_0};\n+\t\t\tmask[idx] = 0xffff0000;\n+\t\t} else {\n+\t\t\tif (!data->offset)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DMAC_47_16};\n+\t\t\tinfo[idx] = (struct field_modify_info){2, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DMAC_15_0};\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_MAC_SRC:\n+\t\tif (mask) {\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SMAC_47_16};\n+\t\t\tmask[idx] = (data->offset == 32) ? 0x0 : 0xffffffff;\n+\t\t\t++idx;\n+\t\t\tinfo[idx] = (struct field_modify_info){2, 4,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SMAC_15_0};\n+\t\t\tmask[idx] = 0xffff0000;\n+\t\t} else {\n+\t\t\tif (!data->offset)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SMAC_47_16};\n+\t\t\tinfo[idx] = (struct field_modify_info){2, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SMAC_15_0};\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_VLAN_TYPE:\n+\t\t/* not supported yet */\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_VLAN_ID:\n+\t\tinfo[idx] = (struct field_modify_info){2, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_FIRST_VID};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xfffff000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_MAC_TYPE:\n+\t\tinfo[idx] = (struct field_modify_info){2, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_ETHERTYPE};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffff0000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_IPV4_DSCP:\n+\t\tinfo[idx] = (struct field_modify_info){1, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_IP_DSCP};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xfc000000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_IPV4_TTL:\n+\t\tinfo[idx] = (struct field_modify_info){1, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_IPV4_TTL};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xff000000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_IPV4_SRC:\n+\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_SIPV4};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffffffff;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_IPV4_DST:\n+\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_DIPV4};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffffffff;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_IPV6_HOPLIMIT:\n+\t\tinfo[idx] = (struct field_modify_info){1, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_IPV6_HOPLIMIT};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xff000000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_IPV6_SRC:\n+\t\tif (mask) {\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SIPV6_127_96};\n+\t\t\tmask[idx] = (data->offset >= 32) ? 0x0 : 0xffffffff;\n+\t\t\t++idx;\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 4,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SIPV6_95_64};\n+\t\t\tmask[idx] = (data->offset >= 64) ? 0x0 : 0xffffffff;\n+\t\t\t++idx;\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 8,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SIPV6_63_32};\n+\t\t\tmask[idx] = (data->offset >= 96) ? 0x0 : 0xffffffff;\n+\t\t\t++idx;\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 12,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SIPV6_31_0};\n+\t\t\tmask[idx] = 0xffffffff;\n+\t\t} else {\n+\t\t\tif (data->offset < 32)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SIPV6_127_96};\n+\t\t\tif (data->offset < 64)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SIPV6_95_64};\n+\t\t\tif (data->offset < 96)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SIPV6_63_32};\n+\t\t\tif (data->offset < 128)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_SIPV6_31_0};\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_IPV6_DST:\n+\t\tif (mask) {\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DIPV6_127_96};\n+\t\t\tmask[idx] = (data->offset >= 32) ? 0x0 : 0xffffffff;\n+\t\t\t++idx;\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 4,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DIPV6_95_64};\n+\t\t\tmask[idx] = (data->offset >= 64) ? 0x0 : 0xffffffff;\n+\t\t\t++idx;\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 8,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DIPV6_63_32};\n+\t\t\tmask[idx] = (data->offset >= 96) ? 0x0 : 0xffffffff;\n+\t\t\t++idx;\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 12,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DIPV6_31_0};\n+\t\t\tmask[idx] = 0xffffffff;\n+\t\t} else {\n+\t\t\tif (data->offset < 32)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DIPV6_127_96};\n+\t\t\tif (data->offset < 64)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DIPV6_95_64};\n+\t\t\tif (data->offset < 96)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DIPV6_63_32};\n+\t\t\tif (data->offset < 128)\n+\t\t\t\tinfo[idx++] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\tMLX5_MODI_OUT_DIPV6_31_0};\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_TCP_PORT_SRC:\n+\t\tinfo[idx] = (struct field_modify_info){2, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_TCP_SPORT};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffff0000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_TCP_PORT_DST:\n+\t\tinfo[idx] = (struct field_modify_info){2, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_TCP_DPORT};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffff0000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_TCP_SEQ_NUM:\n+\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_TCP_SEQ_NUM};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffffffff;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_TCP_ACK_NUM:\n+\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_TCP_ACK_NUM};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffffffff;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_TCP_FLAGS:\n+\t\tinfo[idx] = (struct field_modify_info){1, 0,\n+\t\t\t\t\tMLX5_MODI_IN_TCP_FLAGS};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xfc000000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_UDP_PORT_SRC:\n+\t\tinfo[idx] = (struct field_modify_info){2, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_UDP_SPORT};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffff0000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_UDP_PORT_DST:\n+\t\tinfo[idx] = (struct field_modify_info){2, 0,\n+\t\t\t\t\tMLX5_MODI_OUT_UDP_DPORT};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffff0000;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_VXLAN_VNI:\n+\t\t/* not supported yet */\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_GENEVE_VNI:\n+\t\t/* not supported yet*/\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_GTP_TEID:\n+\t\tinfo[idx] = (struct field_modify_info){4, 0, 0x6E};\n+\t\tif (mask)\n+\t\t\tmask[idx] = 0xffffffff;\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_TAG:\n+\t\t{\n+\t\t\tint ret;\n+\t\t\tenum mlx5_modification_field reg_type;\n+\t\t\tret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG,\n+\t\t\t\t\t\t   data->level, error);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn;\n+\t\t\tMLX5_ASSERT(ret != REG_NON);\n+\t\t\tMLX5_ASSERT((unsigned int)ret < RTE_DIM(reg_to_field));\n+\t\t\treg_type = reg_to_field[ret];\n+\t\t\tMLX5_ASSERT(reg_type > 0);\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 0, reg_type};\n+\t\t\tif (mask)\n+\t\t\t\tmask[idx] = 0xffffffff;\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_MARK:\n+\t\t{\n+\t\t\tint reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK,\n+\t\t\t\t\t\t       0, error);\n+\t\t\tif (reg < 0)\n+\t\t\t\treturn;\n+\t\t\tMLX5_ASSERT(reg > 0);\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\treg_to_field[reg]};\n+\t\t\tif (mask)\n+\t\t\t\tmask[idx] = 0xffffffff;\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_META:\n+\t\t{\n+\t\t\tint reg = flow_dv_get_metadata_reg(dev, attr, error);\n+\t\t\tif (reg < 0)\n+\t\t\t\treturn;\n+\t\t\tMLX5_ASSERT(reg != REG_NON);\n+\t\t\tinfo[idx] = (struct field_modify_info){4, 0,\n+\t\t\t\t\t\treg_to_field[reg]};\n+\t\t\tif (mask)\n+\t\t\t\tmask[idx] = 0xffffffff;\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_FLOW_FIELD_POINTER:\n+\t\tfor (idx = 0; idx < MLX5DV_FLOW_MAX_MOD_FIELDS; idx++) {\n+\t\t\tif (mask[idx]) {\n+\t\t\t\tvalue[idx] = RTE_BE32(*(uint64_t *)data->value);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\tcase RTE_FLOW_FIELD_VALUE:\n+\t\tfor (idx = 0; idx < MLX5DV_FLOW_MAX_MOD_FIELDS; idx++) {\n+\t\t\tif (mask[idx]) {\n+\t\t\t\tvalue[idx] = RTE_BE32(data->value);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tMLX5_ASSERT(false);\n+\t\tbreak;\n+\t}\n+}\n+\n+/**\n+ * Convert modify_field action to DV specification.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte_eth_dev structure.\n+ * @param[in,out] resource\n+ *   Pointer to the modify-header resource.\n+ * @param[in] action\n+ *   Pointer to action specification.\n+ * @param[in] attr\n+ *   Attributes of flow that includes this item.\n+ * @param[out] error\n+ *   Pointer to the error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+flow_dv_convert_action_modify_field\n+\t\t\t(struct rte_eth_dev *dev,\n+\t\t\t struct mlx5_flow_dv_modify_hdr_resource *resource,\n+\t\t\t const struct rte_flow_action *action,\n+\t\t\t const struct rte_flow_attr *attr,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_action_modify_field *conf =\n+\t\t(const struct rte_flow_action_modify_field *)(action->conf);\n+\tstruct rte_flow_item item;\n+\tstruct field_modify_info field[MLX5DV_FLOW_MAX_MOD_FIELDS] = {\n+\t\t\t\t\t\t\t\t{0, 0, 0} };\n+\tstruct field_modify_info dcopy[MLX5DV_FLOW_MAX_MOD_FIELDS] = {\n+\t\t\t\t\t\t\t\t{0, 0, 0} };\n+\tuint32_t mask[MLX5DV_FLOW_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0};\n+\tuint32_t value[MLX5DV_FLOW_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0};\n+\tuint32_t type;\n+\n+\tif (conf->src.field == RTE_FLOW_FIELD_POINTER ||\n+\t\tconf->src.field == RTE_FLOW_FIELD_VALUE) {\n+\t\ttype = MLX5_MODIFICATION_TYPE_SET;\n+\t\t/** For SET fill the destination field (field) first. */\n+\t\tmlx5_flow_field_id_to_modify_info(&conf->dst, field, mask,\n+\t\t\t\t\t\t  value, dev, attr, error);\n+\t\t/** Then copy immediate value from source as per mask. */\n+\t\tmlx5_flow_field_id_to_modify_info(&conf->src, dcopy, mask,\n+\t\t\t\t\t\t  value, dev, attr, error);\n+\t\titem.spec = &value;\n+\t} else {\n+\t\ttype = MLX5_MODIFICATION_TYPE_COPY;\n+\t\t/** For COPY fill the destination field (dcopy) without mask. */\n+\t\tmlx5_flow_field_id_to_modify_info(&conf->dst, dcopy, NULL,\n+\t\t\t\t\t\t  value, dev, attr, error);\n+\t\t/** Then cnstruct th source field (field) with mask. */\n+\t\tmlx5_flow_field_id_to_modify_info(&conf->src, field, mask,\n+\t\t\t\t\t\t  value, dev, attr, error);\n+\t}\n+\titem.mask = &mask;\n+\treturn flow_dv_convert_modify_action(&item,\n+\t\t\tfield, dcopy, resource, type, error);\n+}\n+\n /**\n  * Validate MARK item.\n  *\n@@ -3985,6 +4323,148 @@ flow_dv_validate_action_modify_ttl(const uint64_t action_flags,\n \treturn ret;\n }\n \n+static int\n+mlx5_flow_item_field_width(enum rte_flow_field_id field)\n+{\n+\tswitch (field) {\n+\tcase RTE_FLOW_FIELD_START:\n+\t\treturn 32;\n+\tcase RTE_FLOW_FIELD_MAC_DST:\n+\tcase RTE_FLOW_FIELD_MAC_SRC:\n+\t\treturn 48;\n+\tcase RTE_FLOW_FIELD_VLAN_TYPE:\n+\t\treturn 16;\n+\tcase RTE_FLOW_FIELD_VLAN_ID:\n+\t\treturn 12;\n+\tcase RTE_FLOW_FIELD_MAC_TYPE:\n+\t\treturn 16;\n+\tcase RTE_FLOW_FIELD_IPV4_DSCP:\n+\tcase RTE_FLOW_FIELD_IPV4_TTL:\n+\t\treturn 8;\n+\tcase RTE_FLOW_FIELD_IPV4_SRC:\n+\tcase RTE_FLOW_FIELD_IPV4_DST:\n+\t\treturn 32;\n+\tcase RTE_FLOW_FIELD_IPV6_HOPLIMIT:\n+\t\treturn 8;\n+\tcase RTE_FLOW_FIELD_IPV6_SRC:\n+\tcase RTE_FLOW_FIELD_IPV6_DST:\n+\t\treturn 128;\n+\tcase RTE_FLOW_FIELD_TCP_PORT_SRC:\n+\tcase RTE_FLOW_FIELD_TCP_PORT_DST:\n+\t\treturn 16;\n+\tcase RTE_FLOW_FIELD_TCP_SEQ_NUM:\n+\tcase RTE_FLOW_FIELD_TCP_ACK_NUM:\n+\t\treturn 32;\n+\tcase RTE_FLOW_FIELD_TCP_FLAGS:\n+\t\treturn 6;\n+\tcase RTE_FLOW_FIELD_UDP_PORT_SRC:\n+\tcase RTE_FLOW_FIELD_UDP_PORT_DST:\n+\t\treturn 16;\n+\tcase RTE_FLOW_FIELD_VXLAN_VNI:\n+\tcase RTE_FLOW_FIELD_GENEVE_VNI:\n+\t\treturn 24;\n+\tcase RTE_FLOW_FIELD_GTP_TEID:\n+\tcase RTE_FLOW_FIELD_TAG:\n+\tcase RTE_FLOW_FIELD_MARK:\n+\tcase RTE_FLOW_FIELD_META:\n+\tcase RTE_FLOW_FIELD_POINTER:\n+\tcase RTE_FLOW_FIELD_VALUE:\n+\t\treturn 32;\n+\tdefault:\n+\t\tMLX5_ASSERT(false);\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Validate the generic modify field actions.\n+ *\n+ * @param[in] action_flags\n+ *   Holds the actions detected until now.\n+ * @param[in] action\n+ *   Pointer to the modify action.\n+ * @param[in] item_flags\n+ *   Holds the items detected.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *   Number of header fields to modify (0 or more) on success,\n+ *   a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+flow_dv_validate_action_modify_field(const uint64_t action_flags,\n+\t\t\t\t   const struct rte_flow_action *action,\n+\t\t\t\t   struct rte_flow_error *error)\n+{\n+\tint ret = 0;\n+\tconst struct rte_flow_action_modify_field *action_modify_field =\n+\t\taction->conf;\n+\tuint32_t dst_width =\n+\t\tmlx5_flow_item_field_width(action_modify_field->dst.field);\n+\tuint32_t src_width =\n+\t\tmlx5_flow_item_field_width(action_modify_field->src.field);\n+\n+\tret = flow_dv_validate_action_modify_hdr(action_flags, action, error);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (action_modify_field->src.field != RTE_FLOW_FIELD_VALUE &&\n+\t    action_modify_field->src.field != RTE_FLOW_FIELD_POINTER) {\n+\t\tif (action_modify_field->dst.offset >= dst_width ||\n+\t\t    (action_modify_field->dst.offset % 32) ||\n+\t\t    action_modify_field->src.offset >= src_width ||\n+\t\t    (action_modify_field->src.offset % 32))\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\tNULL,\n+\t\t\t\t\t\t\"offset is too big\"\n+\t\t\t\t\t\t\" or not aligned to 4 bytes\");\n+\t\tif ((action_modify_field->dst.level &&\n+\t\t     action_modify_field->dst.field != RTE_FLOW_FIELD_TAG) ||\n+\t\t    (action_modify_field->src.level &&\n+\t\t     action_modify_field->src.field != RTE_FLOW_FIELD_TAG))\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\tNULL,\n+\t\t\t\t\t\t\"inner header modifications\"\n+\t\t\t\t\t\t\" are not supported\");\n+\t}\n+\tif (action_modify_field->width == 0)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\tNULL,\n+\t\t\t\t\t\t\"width is required for modify action\");\n+\tif (action_modify_field->dst.field ==\n+\t    action_modify_field->src.field)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\tNULL,\n+\t\t\t\t\t\"source and destination fields\"\n+\t\t\t\t\t\" cannot be the same\");\n+\tif (action_modify_field->dst.field == RTE_FLOW_FIELD_VALUE ||\n+\t    action_modify_field->dst.field == RTE_FLOW_FIELD_POINTER)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\tNULL,\n+\t\t\t\t\t\"immediate value or a pointer to it\"\n+\t\t\t\t\t\" cannot be used as a destination\");\n+\tif (action_modify_field->dst.field == RTE_FLOW_FIELD_START)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\tNULL,\n+\t\t\t\t\"modifications of an arbitrary\"\n+\t\t\t\t\" place in a packet is not supported\");\n+\tif (action_modify_field->operation != RTE_FLOW_MODIFY_SET)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\tNULL,\n+\t\t\t\t\"add and sub operations\"\n+\t\t\t\t\" are not supported\");\n+\treturn (action_modify_field->width / 32) +\n+\t       !!(action_modify_field->width % 32);\n+}\n+\n /**\n  * Validate jump action.\n  *\n@@ -5373,7 +5853,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \tstruct mlx5_dev_config *dev_conf = &priv->config;\n \tuint16_t queue_index = 0xFFFF;\n \tconst struct rte_flow_item_vlan *vlan_m = NULL;\n-\tint16_t rw_act_num = 0;\n+\tuint32_t rw_act_num = 0;\n \tuint64_t is_root;\n \tconst struct mlx5_flow_tunnel *tunnel;\n \tstruct flow_grp_info grp_info = {\n@@ -6169,6 +6649,23 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \n \t\t\taction_flags |= MLX5_FLOW_ACTION_TUNNEL_SET;\n \t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:\n+\t\t\tif (!attr->transfer && !attr->group)\n+\t\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\tNULL, \"modify field action \"\n+\t\t\t\t\t\t\"is not supported for group 0\");\n+\t\t\tret = flow_dv_validate_action_modify_field(action_flags,\n+\t\t\t\t\t\t\t\t actions,\n+\t\t\t\t\t\t\t\t error);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn ret;\n+\t\t\t/* Count all modify-header actions as one action. */\n+\t\t\tif (!(action_flags & MLX5_FLOW_ACTION_MODIFY_FIELD))\n+\t\t\t\t++actions_n;\n+\t\t\taction_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;\n+\t\t\trw_act_num += ret;\n+\t\t\tbreak;\n \t\tdefault:\n \t\t\treturn rte_flow_error_set(error, ENOTSUP,\n \t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n@@ -6326,7 +6823,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \t    dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&\n \t    mlx5_flow_ext_mreg_supported(dev))\n \t\trw_act_num += MLX5_ACT_NUM_SET_TAG;\n-\tif ((uint32_t)rw_act_num >\n+\tif (rw_act_num >\n \t\t\tflow_dv_modify_hdr_action_max(dev, is_root)) {\n \t\treturn rte_flow_error_set(error, ENOTSUP,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n@@ -10686,6 +11183,12 @@ flow_dv_translate(struct rte_eth_dev *dev,\n \t\t\t\tsample_act->action_flags |=\n \t\t\t\t\t\t\tMLX5_FLOW_ACTION_ENCAP;\n \t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:\n+\t\t\tif (flow_dv_convert_action_modify_field\n+\t\t\t\t\t(dev, mhdr_res, actions, attr, error))\n+\t\t\t\treturn -rte_errno;\n+\t\t\taction_flags |= MLX5_FLOW_ACTION_MODIFY_FIELD;\n+\t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_END:\n \t\t\tactions_end = true;\n \t\t\tif (mhdr_res->actions_num) {\n",
    "prefixes": []
}