get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 135194,
    "url": "http://patches.dpdk.org/api/patches/135194/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20231214105813.570597-1-psatheesh@marvell.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20231214105813.570597-1-psatheesh@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20231214105813.570597-1-psatheesh@marvell.com",
    "date": "2023-12-14T10:58:11",
    "name": "[1/3] common/cnxk: support mirror flow action",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "acf566dbab90426989e0e1f402100cb082792a11",
    "submitter": {
        "id": 1663,
        "url": "http://patches.dpdk.org/api/people/1663/?format=api",
        "name": "Satheesh Paul Antonysamy",
        "email": "psatheesh@marvell.com"
    },
    "delegate": {
        "id": 310,
        "url": "http://patches.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20231214105813.570597-1-psatheesh@marvell.com/mbox/",
    "series": [
        {
            "id": 30552,
            "url": "http://patches.dpdk.org/api/series/30552/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=30552",
            "date": "2023-12-14T10:58:11",
            "name": "[1/3] common/cnxk: support mirror flow action",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/30552/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/135194/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/135194/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 98565436EE;\n\tThu, 14 Dec 2023 11:58:23 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 3C15C42FFD;\n\tThu, 14 Dec 2023 11:58:23 +0100 (CET)",
            "from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com\n [67.231.148.174])\n by mails.dpdk.org (Postfix) with ESMTP id DB90B40697\n for <dev@dpdk.org>; Thu, 14 Dec 2023 11:58:21 +0100 (CET)",
            "from pps.filterd (m0045849.ppops.net [127.0.0.1])\n by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id\n 3BE9LPYr002192 for <dev@dpdk.org>; Thu, 14 Dec 2023 02:58:21 -0800",
            "from dc5-exch01.marvell.com ([199.233.59.181])\n by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3uyy0m89b1-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)\n for <dev@dpdk.org>; Thu, 14 Dec 2023 02:58:20 -0800 (PST)",
            "from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com\n (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48;\n Thu, 14 Dec 2023 02:58:19 -0800",
            "from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend\n Transport; Thu, 14 Dec 2023 02:58:19 -0800",
            "from satheeshpaullabpc.. (unknown [10.28.34.33])\n by maili.marvell.com (Postfix) with ESMTP id B2B2A3F70B8;\n Thu, 14 Dec 2023 02:58:16 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=\n from:to:cc:subject:date:message-id:mime-version\n :content-transfer-encoding:content-type; s=pfpt0220; bh=oISolZ22\n 6+KCdV4d8WmRfWH6tQEr8gmFY0fVt2w2pVc=; b=JKSABEjdym5ONYhvR83fx6Yp\n cAphirvB3p8pKbkyOdFZIH6hLc/drTgUwrkW6trMZcCDP4/maTkaVOiwO2p/FgUr\n qoaicvJ+Vqkr9CDRY3gEUjN2lFXVFbZM/JT/wblW/e6y3WP6PlHcwSPK866imhXk\n S/+ZE7L7TZV5wopMAoVKXQtiZ5Nni7rkKfEd5eNTIUweGiAFVvbpVsrvy+lpeLcL\n Um5tO4yt8ZhzSd+bC1tTsKU8bZRXDXaHScxy7TDoPUmVIS9uLsM9Ez997RrcmA9H\n ixojVYa9oQk2q7S/K4w5APXAqW7W7PkJ1UEepzDsaDOMJGpWfm39sONZvtRRcg==",
        "From": "<psatheesh@marvell.com>",
        "To": "Nithin Dabilpuram <ndabilpuram@marvell.com>, Kiran Kumar K\n <kirankumark@marvell.com>, Sunil Kumar Kori <skori@marvell.com>, Satha Rao\n <skoteshwar@marvell.com>",
        "CC": "<dev@dpdk.org>, Satheesh Paul <psatheesh@marvell.com>",
        "Subject": "[dpdk-dev] [PATCH 1/3] common/cnxk: support mirror flow action",
        "Date": "Thu, 14 Dec 2023 16:28:11 +0530",
        "Message-ID": "<20231214105813.570597-1-psatheesh@marvell.com>",
        "X-Mailer": "git-send-email 2.39.2",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Proofpoint-GUID": "wzft1O3GeuwCiTpZ2MEEyPmZh09FoDUf",
        "X-Proofpoint-ORIG-GUID": "wzft1O3GeuwCiTpZ2MEEyPmZh09FoDUf",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26\n definitions=2023-12-09_02,2023-12-07_01,2023-05-22_02",
        "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"
    },
    "content": "From: Satheesh Paul <psatheesh@marvell.com>\n\nAdd ROC API to support mirror flow action.\n\nSigned-off-by: Satheesh Paul <psatheesh@marvell.com>\nReviewed-by: Kiran Kumar K <kirankumark@marvell.com>\n---\n drivers/common/cnxk/roc_mbox.h      | 56 +++++++++++++++++\n drivers/common/cnxk/roc_nix.h       |  8 ++-\n drivers/common/cnxk/roc_nix_mcast.c | 86 ++++++++++++++++++++++++++\n drivers/common/cnxk/roc_npc.c       | 94 +++++++++++++++++++++++++----\n drivers/common/cnxk/roc_npc.h       | 19 +++++-\n drivers/common/cnxk/roc_npc_mcam.c  | 56 +++++++++++++----\n drivers/common/cnxk/roc_npc_priv.h  |  3 +-\n drivers/common/cnxk/version.map     |  2 +\n 8 files changed, 295 insertions(+), 29 deletions(-)",
    "diff": "diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h\nindex 05434aec5a..3257a370bc 100644\n--- a/drivers/common/cnxk/roc_mbox.h\n+++ b/drivers/common/cnxk/roc_mbox.h\n@@ -298,6 +298,11 @@ struct mbox_msghdr {\n \tM(NIX_FREE_BPIDS, 0x8029, nix_free_bpids, nix_bpids, msg_rsp)          \\\n \tM(NIX_RX_CHAN_CFG, 0x802a, nix_rx_chan_cfg, nix_rx_chan_cfg,           \\\n \t  nix_rx_chan_cfg)                                                     \\\n+\tM(NIX_MCAST_GRP_CREATE, 0x802b, nix_mcast_grp_create, nix_mcast_grp_create_req,            \\\n+\t  nix_mcast_grp_create_rsp)                                                                \\\n+\tM(NIX_MCAST_GRP_DESTROY, 0x802c, nix_mcast_grp_destroy, nix_mcast_grp_destroy_req, msg_rsp)\\\n+\tM(NIX_MCAST_GRP_UPDATE, 0x802d, nix_mcast_grp_update, nix_mcast_grp_update_req,            \\\n+\t  nix_mcast_grp_update_rsp)                                                                \\\n \t/* MCS mbox IDs (range 0xa000 - 0xbFFF) */                                                 \\\n \tM(MCS_ALLOC_RESOURCES, 0xa000, mcs_alloc_resources, mcs_alloc_rsrc_req,                    \\\n \t  mcs_alloc_rsrc_rsp)                                                                      \\\n@@ -1768,6 +1773,57 @@ struct nix_rx_chan_cfg {\n \tuint64_t __io rsvd;\n };\n \n+struct nix_mcast_grp_create_req {\n+\tstruct mbox_msghdr hdr;\n+#define NIX_MCAST_INGRESS 0\n+#define NIX_MCAST_EGRESS  1\n+\tuint8_t __io dir;\n+\tuint8_t __io reserved[11];\n+\t/* Reserving few bytes for future requirement */\n+};\n+\n+struct nix_mcast_grp_create_rsp {\n+\tstruct mbox_msghdr hdr;\n+\t/* This mcast_grp_idx should be passed during MCAM\n+\t * write entry for multicast. AF will identify the\n+\t * corresponding multicast table index associated\n+\t * with the group id and program the same to MCAM entry.\n+\t * This group id is also needed during group delete\n+\t * and update request.\n+\t */\n+\tuint32_t __io mcast_grp_idx;\n+};\n+struct nix_mcast_grp_destroy_req {\n+\tstruct mbox_msghdr hdr;\n+\t/* Group id returned by nix_mcast_grp_create_rsp */\n+\tuint32_t __io mcast_grp_idx;\n+};\n+\n+struct nix_mcast_grp_update_req {\n+\tstruct mbox_msghdr hdr;\n+\t/* Group id returned by nix_mcast_grp_create_rsp */\n+\tuint32_t __io mcast_grp_idx;\n+\t/* Number of multicast/mirror entries requested */\n+\tuint32_t __io num_mce_entry;\n+#define NIX_MCE_ENTRY_MAX 64\n+#define NIX_RX_RQ\t  0\n+#define NIX_RX_RSS\t  1\n+\t/* Receive queue or RSS index within pf_func */\n+\tuint32_t __io rq_rss_index[NIX_MCE_ENTRY_MAX];\n+\tuint16_t __io pcifunc[NIX_MCE_ENTRY_MAX];\n+\tuint16_t __io channel[NIX_MCE_ENTRY_MAX];\n+#define NIX_MCAST_OP_ADD_ENTRY 0\n+#define NIX_MCAST_OP_DEL_ENTRY 1\n+\t/* Destination type. 0:Receive queue, 1:RSS*/\n+\tuint8_t __io dest_type[NIX_MCE_ENTRY_MAX];\n+\tuint8_t __io op;\n+};\n+\n+struct nix_mcast_grp_update_rsp {\n+\tstruct mbox_msghdr hdr;\n+\tuint32_t __io mce_start_index;\n+};\n+\n /* Global NIX inline IPSec configuration */\n struct nix_inline_ipsec_cfg {\n \tstruct mbox_msghdr hdr;\ndiff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h\nindex 82997c38ce..c1ebf971f7 100644\n--- a/drivers/common/cnxk/roc_nix.h\n+++ b/drivers/common/cnxk/roc_nix.h\n@@ -1005,6 +1005,10 @@ int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,\n \t\t\t\t\t     struct mcam_entry *entry,\n \t\t\t\t\t     uint32_t index, uint8_t intf,\n \t\t\t\t\t     uint64_t action);\n-int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix,\n-\t\t\t\t\t       uint32_t index, bool enable);\n+int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,\n+\t\t\t\t\t       bool enable);\n+int __roc_api roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries,\n+\t\t\t\t       uint16_t *pf_funcs, uint16_t *channels, uint32_t *rqs,\n+\t\t\t\t       uint32_t *grp_index, uint32_t *start_index);\n+int __roc_api roc_nix_mcast_list_free(struct mbox *mbox, uint32_t mcast_grp_index);\n #endif /* _ROC_NIX_H_ */\ndiff --git a/drivers/common/cnxk/roc_nix_mcast.c b/drivers/common/cnxk/roc_nix_mcast.c\nindex 3d74111274..615014e820 100644\n--- a/drivers/common/cnxk/roc_nix_mcast.c\n+++ b/drivers/common/cnxk/roc_nix_mcast.c\n@@ -107,3 +107,89 @@ roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,\n \tmbox_put(mbox);\n \treturn rc;\n }\n+\n+int\n+roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries, uint16_t *pf_funcs,\n+\t\t\t uint16_t *channels, uint32_t *rqs, uint32_t *grp_index,\n+\t\t\t uint32_t *start_index)\n+{\n+\tstruct nix_mcast_grp_create_req *mce_grp_create_req;\n+\tstruct nix_mcast_grp_create_rsp *mce_grp_create_rsp;\n+\tstruct nix_mcast_grp_update_req *mce_grp_update_req;\n+\tstruct nix_mcast_grp_update_rsp *mce_grp_update_rsp;\n+\tint rc = 0, i;\n+\n+\tmbox_get(mbox);\n+\n+\tmce_grp_create_req = mbox_alloc_msg_nix_mcast_grp_create(mbox);\n+\tif (mce_grp_create_req == NULL) {\n+\t\trc = -ENOSPC;\n+\t\tgoto exit;\n+\t}\n+\n+\tmce_grp_create_req->dir = intf;\n+\trc = mbox_process_msg(mbox, (void *)&mce_grp_create_rsp);\n+\tif (rc) {\n+\t\tplt_err(\"Failed to create mirror list\");\n+\t\tgoto exit;\n+\t}\n+\n+\t*grp_index = mce_grp_create_rsp->mcast_grp_idx;\n+\n+\tmce_grp_update_req = mbox_alloc_msg_nix_mcast_grp_update(mbox);\n+\tif (mce_grp_update_req == NULL) {\n+\t\trc = -ENOSPC;\n+\t\tgoto exit;\n+\t}\n+\n+\tmce_grp_update_req->mcast_grp_idx = *grp_index;\n+\tmce_grp_update_req->op = NIX_MCAST_OP_ADD_ENTRY;\n+\tmce_grp_update_req->num_mce_entry = nb_entries;\n+\tfor (i = 0; i < nb_entries; i++) {\n+\t\tmce_grp_update_req->pcifunc[i] = pf_funcs[i];\n+\t\tmce_grp_update_req->channel[i] = channels[i];\n+\t\tmce_grp_update_req->rq_rss_index[i] = rqs[i];\n+\t\tmce_grp_update_req->dest_type[i] = NIX_RX_RQ;\n+\t}\n+\n+\trc = mbox_process_msg(mbox, (void *)&mce_grp_update_rsp);\n+\tif (rc) {\n+\t\tplt_err(\"Failed to create mirror list\");\n+\t\tgoto exit;\n+\t}\n+\n+\t*start_index = (mce_grp_update_rsp->mce_start_index & 0xFFFFF);\n+\n+\trc = 0;\n+exit:\n+\tmbox_put(mbox);\n+\treturn rc;\n+}\n+\n+int\n+roc_nix_mcast_list_free(struct mbox *mbox, uint32_t mcast_grp_index)\n+{\n+\tstruct nix_mcast_grp_destroy_req *mce_grp_destroy_req;\n+\tstruct nix_mcast_grp_destroy_rsp *mce_grp_destroy_rsp;\n+\tint rc = 0;\n+\n+\tmbox_get(mbox);\n+\n+\tmce_grp_destroy_req = mbox_alloc_msg_nix_mcast_grp_destroy(mbox);\n+\tif (mce_grp_destroy_req == NULL) {\n+\t\trc = -ENOSPC;\n+\t\tgoto exit;\n+\t}\n+\n+\tmce_grp_destroy_req->mcast_grp_idx = mcast_grp_index;\n+\trc = mbox_process_msg(mbox, (void *)&mce_grp_destroy_rsp);\n+\tif (rc) {\n+\t\tplt_err(\"Failed to destroy mirror group index\");\n+\t\tgoto exit;\n+\t}\n+\n+\trc = 0;\n+exit:\n+\tmbox_put(mbox);\n+\treturn rc;\n+}\ndiff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c\nindex 1958b3089d..65f99549c9 100644\n--- a/drivers/common/cnxk/roc_npc.c\n+++ b/drivers/common/cnxk/roc_npc.c\n@@ -497,6 +497,39 @@ npc_parse_spi_to_sa_action(struct roc_npc *roc_npc, const struct roc_npc_action\n \treturn 0;\n }\n \n+static int\n+roc_npc_process_sample_action(struct roc_npc *roc_npc,\n+\t\t\t      const struct roc_npc_action_sample *sample_action,\n+\t\t\t      struct roc_npc_flow *flow)\n+{\n+\tstruct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix);\n+\tstruct npc *npc = roc_npc_to_npc_priv(roc_npc);\n+\n+\tflow->is_sampling_rule = true;\n+\n+\tswitch (sample_action->action_type) {\n+\tcase ROC_NPC_ACTION_TYPE_PORT_ID:\n+\t\tflow->mcast_pf_funcs[0] = sample_action->pf_func;\n+\t\tflow->mcast_channels[0] = sample_action->channel;\n+\t\tbreak;\n+\tcase ROC_NPC_ACTION_TYPE_PF:\n+\t\tflow->mcast_pf_funcs[0] = roc_npc->pf_func;\n+\t\tflow->mcast_channels[0] = npc->channel;\n+\t\tbreak;\n+\tcase ROC_NPC_ACTION_TYPE_VF:\n+\t\tif (sample_action->pf_func >= nix->dev.maxvf)\n+\t\t\treturn -EINVAL;\n+\t\tflow->mcast_pf_funcs[0] =\n+\t\t\t((roc_npc->pf_func & 0xfc00) | (sample_action->pf_func + 1));\n+\t\tflow->mcast_channels[0] = npc->channel;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int\n npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t  const struct roc_npc_action actions[], struct roc_npc_flow *flow,\n@@ -504,6 +537,7 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n {\n \tstruct npc *npc = roc_npc_to_npc_priv(roc_npc);\n \tconst struct roc_npc_action *sec_action = NULL;\n+\tconst struct roc_npc_action_sample *act_sample;\n \tconst struct roc_npc_action_mark *act_mark;\n \tconst struct roc_npc_action_meter *act_mtr;\n \tconst struct roc_npc_action_queue *act_q;\n@@ -562,8 +596,7 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t\tbreak;\n \n \t\tcase ROC_NPC_ACTION_TYPE_VF:\n-\t\t\tvf_act =\n-\t\t\t\t(const struct roc_npc_action_vf *)actions->conf;\n+\t\t\tvf_act = (const struct roc_npc_action_vf *)actions->conf;\n \t\t\treq_act |= ROC_NPC_ACTION_TYPE_VF;\n \t\t\tvf_id = vf_act->id & RVU_PFVF_FUNC_MASK;\n \t\t\tpf_func &= (0xfc00);\n@@ -576,9 +609,8 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t\tbreak;\n \n \t\tcase ROC_NPC_ACTION_TYPE_QUEUE:\n-\t\t\tact_q = (const struct roc_npc_action_queue *)\n-\t\t\t\t\tactions->conf;\n-\t\t\trq = act_q->index;\n+\t\t\tact_q = (const struct roc_npc_action_queue *)actions->conf;\n+\t\t\trq = act_q->index & 0xFFFFF;\n \t\t\treq_act |= ROC_NPC_ACTION_TYPE_QUEUE;\n \t\t\tbreak;\n \n@@ -648,6 +680,13 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t\t\tgoto err_exit;\n \t\t\treq_act |= ROC_NPC_ACTION_TYPE_AGE;\n \t\t\tbreak;\n+\t\tcase ROC_NPC_ACTION_TYPE_SAMPLE:\n+\t\t\treq_act |= ROC_NPC_ACTION_TYPE_SAMPLE;\n+\t\t\tact_sample = actions->conf;\n+\t\t\terrcode = roc_npc_process_sample_action(roc_npc, act_sample, flow);\n+\t\t\tif (errcode)\n+\t\t\t\tgoto err_exit;\n+\t\t\tbreak;\n \t\tdefault:\n \t\t\terrcode = NPC_ERR_ACTION_NOTSUP;\n \t\t\tgoto err_exit;\n@@ -688,6 +727,27 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\tgoto err_exit;\n \t}\n \n+\tif (req_act & ROC_NPC_ACTION_TYPE_SAMPLE) {\n+\t\t/* One entry for the mce list PF and channel comes from the sample subaction.\n+\t\t * Another one is the action target of the flow rule getting created.\n+\t\t */\n+\t\tflow->mcast_pf_funcs[1] = pf_func;\n+\t\tflow->mcast_channels[1] = npc->channel;\n+\t\tif (req_act & (ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_SEC |\n+\t\t\t       ROC_NPC_ACTION_TYPE_RSS)) {\n+\t\t\tplt_err(\"Drop/RSS/SEC not supported with action type sample\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (flow->mcast_pf_funcs[0] == flow->mcast_pf_funcs[1]) {\n+\t\t\tplt_err(\"Sample destination and target cannot be same\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif ((attr->egress) && (flow->mcast_channels[0] == flow->mcast_channels[1])) {\n+\t\t\tplt_err(\"Mirroring within PF and VF not allowed\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n \t/* Check if actions specified are compatible */\n \tif (attr->egress) {\n \t\tif (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) {\n@@ -697,11 +757,10 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t}\n \n \t\tif (req_act &\n-\t\t    ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT |\n-\t\t      ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |\n-\t\t      ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT |\n-\t\t      ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_COUNT)) {\n-\t\t\tplt_err(\"Only VLAN insert, drop, count supported on Egress\");\n+\t\t    ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT | ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |\n+\t\t      ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT | ROC_NPC_ACTION_TYPE_DROP |\n+\t\t      ROC_NPC_ACTION_TYPE_COUNT | ROC_NPC_ACTION_TYPE_SAMPLE)) {\n+\t\t\tplt_err(\"Only VLAN insert, drop, count, sample supported on Egress\");\n \t\t\terrcode = NPC_ERR_ACTION_NOTSUP;\n \t\t\tgoto err_exit;\n \t\t}\n@@ -724,6 +783,11 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t\tgoto err_exit;\n \t\t}\n \n+\t\tif (req_act & ROC_NPC_ACTION_TYPE_SAMPLE) {\n+\t\t\tflow->mcast_pf_funcs[1] = pf_func;\n+\t\t\tflow->mcast_channels[1] = npc->channel;\n+\t\t}\n+\n \t\tgoto set_pf_func;\n \t} else {\n \t\tif (vlan_insert_action) {\n@@ -771,13 +835,13 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t} else {\n \t\t\tflow->npc_action = NIX_RX_ACTIONOP_UCAST;\n \t\t\tif (req_act & ROC_NPC_ACTION_TYPE_QUEUE)\n-\t\t\t\tflow->npc_action |= (uint64_t)rq << 20;\n+\t\t\t\tflow->recv_queue = rq;\n \t\t}\n \t} else if (req_act & ROC_NPC_ACTION_TYPE_DROP) {\n \t\tflow->npc_action = NIX_RX_ACTIONOP_DROP;\n \t} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {\n \t\tflow->npc_action = NIX_RX_ACTIONOP_UCAST;\n-\t\tflow->npc_action |= (uint64_t)rq << 20;\n+\t\tflow->recv_queue = rq;\n \t} else if (req_act & ROC_NPC_ACTION_TYPE_RSS) {\n \t\tflow->npc_action = NIX_RX_ACTIONOP_UCAST;\n \t} else if (req_act & ROC_NPC_ACTION_TYPE_SEC) {\n@@ -797,6 +861,9 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\tgoto err_exit;\n \t}\n \n+\tif (req_act & ROC_NPC_ACTION_TYPE_SAMPLE)\n+\t\tflow->npc_action = NIX_RX_ACTIONOP_MCAST;\n+\n \tif (mark)\n \t\tflow->npc_action |= (uint64_t)mark << 40;\n \n@@ -1639,6 +1706,9 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)\n \t\t\treturn rc;\n \t}\n \n+\tif (flow->is_sampling_rule)\n+\t\troc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);\n+\n \trc = roc_npc_mcam_free(roc_npc, flow);\n \tif (rc != 0)\n \t\treturn rc;\ndiff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h\nindex cb59db2220..e880a7fa67 100644\n--- a/drivers/common/cnxk/roc_npc.h\n+++ b/drivers/common/cnxk/roc_npc.h\n@@ -196,11 +196,19 @@ enum roc_npc_action_type {\n \tROC_NPC_ACTION_TYPE_PORT_ID = (1 << 16),\n \tROC_NPC_ACTION_TYPE_METER = (1 << 17),\n \tROC_NPC_ACTION_TYPE_AGE = (1 << 18),\n+\tROC_NPC_ACTION_TYPE_SAMPLE = (1 << 19),\n };\n \n struct roc_npc_action {\n \tenum roc_npc_action_type type; /**< Action type. */\n-\tconst void *conf; /**< Pointer to action configuration object. */\n+\tconst void *conf;\t       /**< Pointer to action configuration object. */\n+};\n+\n+struct roc_npc_action_sample {\n+\tuint32_t ratio;\t      /**< packets sampled equals to '1/ratio'. */\n+\tuint32_t action_type; /* PF or VF or PORT_ID target. */\n+\tuint16_t pf_func;\n+\tuint16_t channel;\n };\n \n struct roc_npc_action_mark {\n@@ -294,6 +302,8 @@ struct roc_npc_spi_to_sa_action_info {\n \tbool has_action;\n };\n \n+struct mbox;\n+\n struct roc_npc_flow {\n \tuint8_t nix_intf;\n \tuint8_t enable;\n@@ -322,6 +332,13 @@ struct roc_npc_flow {\n \tvoid *age_context;\n \tuint32_t timeout;\n \tbool has_age_action;\n+\tbool is_sampling_rule;\n+\tuint32_t recv_queue;\n+\tuint32_t mcast_grp_index;\n+\tuint32_t mce_start_index;\n+#define ROC_NPC_MIRROR_LIST_SIZE 2\n+\tuint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];\n+\tuint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];\n \n \tTAILQ_ENTRY(roc_npc_flow) next;\n };\ndiff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c\nindex 41edec7d8d..3ef189e184 100644\n--- a/drivers/common/cnxk/roc_npc_mcam.c\n+++ b/drivers/common/cnxk/roc_npc_mcam.c\n@@ -680,6 +680,40 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_\n \t\t}\n \t}\n \n+\tif (flow->nix_intf == NIX_INTF_TX) {\n+\t\tuint16_t pf_func = (flow->npc_action >> 4) & 0xffff;\n+\n+\t\tpf_func = plt_cpu_to_be_16(pf_func);\n+\n+\t\trc = npc_mcam_set_pf_func(npc, flow, pf_func);\n+\t\tif (rc)\n+\t\t\treturn rc;\n+\t}\n+\n+\tif (flow->is_sampling_rule) {\n+\t\t/* Save and restore any mark value set */\n+\t\tuint16_t mark = (flow->npc_action >> 40) & 0xffff;\n+\t\tuint16_t mce_index = 0;\n+\t\tuint32_t rqs[2] = {};\n+\n+\t\trqs[1] = flow->recv_queue;\n+\t\trc = roc_nix_mcast_list_setup(npc->mbox, flow->nix_intf, 2, flow->mcast_pf_funcs,\n+\t\t\t\t\t      flow->mcast_channels, rqs, &flow->mcast_grp_index,\n+\t\t\t\t\t      &flow->mce_start_index);\n+\t\tif (rc)\n+\t\t\treturn rc;\n+\n+\t\tflow->npc_action = NIX_RX_ACTIONOP_MCAST;\n+\t\tmce_index = flow->mce_start_index;\n+\t\tif (flow->nix_intf == NIX_INTF_TX) {\n+\t\t\tflow->npc_action |= (uint64_t)mce_index << 12;\n+\t\t\tflow->npc_action |= (uint64_t)mark << 32;\n+\t\t} else {\n+\t\t\tflow->npc_action |= (uint64_t)mce_index << 20;\n+\t\t\tflow->npc_action |= (uint64_t)mark << 40;\n+\t\t}\n+\t}\n+\n \treq = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));\n \tif (req == NULL) {\n \t\trc = -ENOSPC;\n@@ -691,6 +725,8 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_\n \n \treq->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;\n \treq->enable_entry = 1;\n+\tif (flow->nix_intf == NIX_INTF_RX)\n+\t\tflow->npc_action |= (uint64_t)flow->recv_queue << 20;\n \treq->entry_data.action = flow->npc_action;\n \n \t/*\n@@ -707,16 +743,6 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_\n \t */\n \treq->entry_data.vtag_action = flow->vtag_action;\n \n-\tif (flow->nix_intf == NIX_INTF_TX) {\n-\t\tuint16_t pf_func = (flow->npc_action >> 4) & 0xffff;\n-\n-\t\tpf_func = plt_cpu_to_be_16(pf_func);\n-\n-\t\trc = npc_mcam_set_pf_func(npc, flow, pf_func);\n-\t\tif (rc)\n-\t\t\treturn rc;\n-\t}\n-\n \tfor (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {\n \t\treq->entry_data.kw[idx] = flow->mcam_data[idx];\n \t\treq->entry_data.kw_mask[idx] = flow->mcam_mask[idx];\n@@ -746,7 +772,7 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_\n \t\t */\n \t\tif (pst->is_second_pass_rule || (!pst->is_second_pass_rule && pst->has_eth_type)) {\n \t\t\tla_offset = plt_popcount32(npc->keyx_supp_nmask[flow->nix_intf] &\n-\t\t\t\t\t\t       ((1ULL << 9 /* LA offset */) - 1));\n+\t\t\t\t\t\t   ((1ULL << 9 /* LA offset */) - 1));\n \t\t\tla_offset *= 4;\n \n \t\t\tmask = ~((0xfULL << la_offset));\n@@ -778,8 +804,11 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_\n \tif (flow->use_ctr)\n \t\tflow->ctr_id = ctr;\n \trc = 0;\n+\n exit:\n \tmbox_put(mbox);\n+\tif (rc)\n+\t\troc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);\n \treturn rc;\n }\n \n@@ -836,7 +865,7 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)\n \t */\n \tif (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {\n \t\tlcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &\n-\t\t\t\t\t\t   ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));\n+\t\t\t\t\t       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));\n \t\tlcflag_offset *= 4;\n \n \t\tmask = (0xfULL << lcflag_offset);\n@@ -1020,6 +1049,9 @@ npc_flow_free_all_resources(struct npc *npc)\n \t\t\t\trc |= npc_mcam_free_counter(npc->mbox, flow->ctr_id);\n \t\t\t}\n \n+\t\t\tif (flow->is_sampling_rule)\n+\t\t\t\troc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);\n+\n \t\t\tnpc_delete_prio_list_entry(npc, flow);\n \n \t\t\tTAILQ_REMOVE(&npc->flow_list[idx], flow, next);\ndiff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h\nindex 424f8e207a..c0809407a6 100644\n--- a/drivers/common/cnxk/roc_npc_priv.h\n+++ b/drivers/common/cnxk/roc_npc_priv.h\n@@ -493,8 +493,7 @@ void npc_age_flow_list_entry_delete(struct roc_npc *npc, struct roc_npc_flow *fl\n uint32_t npc_aged_flows_get(void *args);\n int npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc);\n void npc_aged_flows_bitmap_free(struct roc_npc *roc_npc);\n-int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc,\n-\t\t\t\t const struct roc_npc_action_age *age,\n+int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, const struct roc_npc_action_age *age,\n \t\t\t\t struct roc_npc_flow *flow);\n void npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc);\n #endif /* _ROC_NPC_PRIV_H_ */\ndiff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map\nindex 52faf676ba..1b531da36d 100644\n--- a/drivers/common/cnxk/version.map\n+++ b/drivers/common/cnxk/version.map\n@@ -294,6 +294,8 @@ INTERNAL {\n \troc_nix_mac_promisc_mode_enable;\n \troc_nix_mac_rxtx_start_stop;\n \troc_nix_max_pkt_len;\n+\troc_nix_mcast_list_free;\n+\troc_nix_mcast_list_setup;\n \troc_nix_mcast_mcam_entry_alloc;\n \troc_nix_mcast_mcam_entry_ena_dis;\n \troc_nix_mcast_mcam_entry_free;\n",
    "prefixes": [
        "1/3"
    ]
}