get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 129713,
    "url": "http://patchwork.dpdk.org/api/patches/129713/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230727115926.2252988-2-adwivedi@marvell.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20230727115926.2252988-2-adwivedi@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230727115926.2252988-2-adwivedi@marvell.com",
    "date": "2023-07-27T11:59:25",
    "name": "[v1,1/2] common/cnxk: add support to get aged flows",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "6c98528bafce4b8230a2d3b9877cb7fe64384041",
    "submitter": {
        "id": 1561,
        "url": "http://patchwork.dpdk.org/api/people/1561/?format=api",
        "name": "Ankur Dwivedi",
        "email": "adwivedi@marvell.com"
    },
    "delegate": {
        "id": 310,
        "url": "http://patchwork.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20230727115926.2252988-2-adwivedi@marvell.com/mbox/",
    "series": [
        {
            "id": 29022,
            "url": "http://patchwork.dpdk.org/api/series/29022/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=29022",
            "date": "2023-07-27T11:59:24",
            "name": "add support for flow aging in CNXK driver",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/29022/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/129713/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/129713/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 C44EF42F5C;\n\tThu, 27 Jul 2023 13:59:50 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id B67A743248;\n\tThu, 27 Jul 2023 13:59:50 +0200 (CEST)",
            "from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com\n [67.231.148.174])\n by mails.dpdk.org (Postfix) with ESMTP id 436E443247\n for <dev@dpdk.org>; Thu, 27 Jul 2023 13:59:49 +0200 (CEST)",
            "from pps.filterd (m0045849.ppops.net [127.0.0.1])\n by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id\n 36R7Ef0K017424 for <dev@dpdk.org>; Thu, 27 Jul 2023 04:59:48 -0700",
            "from dc5-exch01.marvell.com ([199.233.59.181])\n by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3s3m13rtcn-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)\n for <dev@dpdk.org>; Thu, 27 Jul 2023 04:59:47 -0700",
            "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, 27 Jul 2023 04:59:46 -0700",
            "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, 27 Jul 2023 04:59:46 -0700",
            "from localhost.localdomain (unknown [10.28.36.185])\n by maili.marvell.com (Postfix) with ESMTP id BC7B73F7041;\n Thu, 27 Jul 2023 04:59:43 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;\n h=from : to : cc :\n subject : date : message-id : in-reply-to : references : mime-version :\n content-transfer-encoding : content-type; s=pfpt0220;\n bh=7NJXhBF2OC4S5V3BxfcE/eHUJx4LwCcRW6OiTGm3HBg=;\n b=h5BWQf4LPAZmHTs8FsRjOjyD/NVgjd/ZbnJ7Xqaf2HEjGpWtFnb78d2t5xVQVbbKK+be\n hWkN6zQIo7La3YYXt6B45W/bJlR99X5yXXA6+coW2u6C9H9nFy9YB3UTqVkJ2IooxR4W\n 9LuKSzsbj796n6eoK2sqDLF0A2eAQVklpdZgdcL7AzU10Tl6ltbm8FfN7e5ZrO+JEsjq\n PvPE/1dnzhvn+KC324xk7PW52NxTctT89ItmMv15Z5DhkmDNh/ByNeaLJomPutrGq/CI\n vHndoAmFN2EyEB4DRmC5wDmDEj8AZfIGtD5ye790EwKzPJak3Lh6VS7jrJVkXdgvcXdt Kw==",
        "From": "Ankur Dwivedi <adwivedi@marvell.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<jerinj@marvell.com>, <ndabilpuram@marvell.com>,\n <kirankumark@marvell.com>,\n <skori@marvell.com>, <skoteshwar@marvell.com>,\n Ankur Dwivedi <adwivedi@marvell.com>",
        "Subject": "[PATCH v1 1/2] common/cnxk: add support to get aged flows",
        "Date": "Thu, 27 Jul 2023 17:29:25 +0530",
        "Message-ID": "<20230727115926.2252988-2-adwivedi@marvell.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20230727115926.2252988-1-adwivedi@marvell.com>",
        "References": "<20230727115926.2252988-1-adwivedi@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Proofpoint-GUID": "YKtnzYTvmdtoCeJh_lHQ1Fr7H3r0ZvZD",
        "X-Proofpoint-ORIG-GUID": "YKtnzYTvmdtoCeJh_lHQ1Fr7H3r0ZvZD",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26\n definitions=2023-07-27_06,2023-07-26_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": "Adds support to get aged flows in CNXK driver.\nThe control thread polls the status of flows having age action, every 10\nseconds and updates a bitmap array with the aged flows. The poll frequency\nof control thread can be set by devargs.\n\nSigned-off-by: Ankur Dwivedi <adwivedi@marvell.com>\n---\n drivers/common/cnxk/meson.build     |   1 +\n drivers/common/cnxk/roc_mbox.h      |  27 +++\n drivers/common/cnxk/roc_npc.c       |  22 ++\n drivers/common/cnxk/roc_npc.h       |  28 +++\n drivers/common/cnxk/roc_npc_aging.c | 315 ++++++++++++++++++++++++++++\n drivers/common/cnxk/roc_npc_priv.h  |  17 ++\n drivers/common/cnxk/roc_platform.h  |   8 +\n drivers/common/cnxk/version.map     |   1 +\n 8 files changed, 419 insertions(+)\n create mode 100644 drivers/common/cnxk/roc_npc_aging.c",
    "diff": "diff --git a/drivers/common/cnxk/meson.build b/drivers/common/cnxk/meson.build\nindex 79e10bac74..d5dfd93e31 100644\n--- a/drivers/common/cnxk/meson.build\n+++ b/drivers/common/cnxk/meson.build\n@@ -57,6 +57,7 @@ sources = files(\n         'roc_npa_irq.c',\n         'roc_npa_type.c',\n         'roc_npc.c',\n+        'roc_npc_aging.c',\n         'roc_npc_mcam.c',\n         'roc_npc_mcam_dump.c',\n         'roc_npc_parse.c',\ndiff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h\nindex 2f85b2f755..6db46a86f4 100644\n--- a/drivers/common/cnxk/roc_mbox.h\n+++ b/drivers/common/cnxk/roc_mbox.h\n@@ -227,6 +227,8 @@ struct mbox_msghdr {\n \t  npc_mcam_get_stats_req, npc_mcam_get_stats_rsp)                      \\\n \tM(NPC_GET_FIELD_HASH_INFO, 0x6013, npc_get_field_hash_info,            \\\n \t  npc_get_field_hash_info_req, npc_get_field_hash_info_rsp)            \\\n+\tM(NPC_MCAM_GET_HIT_STATUS, 0x6015, npc_mcam_get_hit_status,            \\\n+\t  npc_mcam_get_hit_status_req, npc_mcam_get_hit_status_rsp)            \\\n \t/* NIX mbox IDs (range 0x8000 - 0xFFFF) */                             \\\n \tM(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, nix_lf_alloc_req,                \\\n \t  nix_lf_alloc_rsp)                                                    \\\n@@ -2466,6 +2468,31 @@ struct npc_mcam_get_stats_rsp {\n \tuint8_t __io stat_ena; /* enabled */\n };\n \n+#define MCAM_ARR_SIZE    256\n+#define MCAM_ARR_ELEM_SZ 64\n+\n+struct npc_mcam_get_hit_status_req {\n+\tstruct mbox_msghdr hdr;\n+\t/* If clear == true, then if the hit status bit for mcam id is set,\n+\t * then needs to cleared by writing 1 back.\n+\t * If clear == false, then leave the hit status bit as is.\n+\t */\n+\tbool __io clear;\n+\tuint8_t __io reserved[3];\n+\t/* Start range of mcam id */\n+\tuint32_t __io range_valid_mcam_ids_start;\n+\t/* End range of mcam id */\n+\tuint32_t __io range_valid_mcam_ids_end;\n+\t/* Bitmap of mcam ids for which the hit status needs to checked */\n+\tuint64_t __io mcam_ids[MCAM_ARR_SIZE];\n+};\n+\n+struct npc_mcam_get_hit_status_rsp {\n+\tstruct mbox_msghdr hdr;\n+\t/* Bitmap of mcam hit status, prior to clearing */\n+\tuint64_t __io mcam_hit_status[MCAM_ARR_SIZE];\n+};\n+\n /* TIM mailbox error codes\n  * Range 801 - 900.\n  */\ndiff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c\nindex 848086c8de..f0bb0aa931 100644\n--- a/drivers/common/cnxk/roc_npc.c\n+++ b/drivers/common/cnxk/roc_npc.c\n@@ -302,6 +302,7 @@ roc_npc_init(struct roc_npc *roc_npc)\n \tnpc_mem = mem;\n \n \tTAILQ_INIT(&npc->ipsec_list);\n+\tTAILQ_INIT(&npc->age_flow_list);\n \tfor (idx = 0; idx < npc->flow_max_priority; idx++) {\n \t\tTAILQ_INIT(&npc->flow_list[idx]);\n \t\tTAILQ_INIT(&npc->prio_flow_list[idx]);\n@@ -330,6 +331,9 @@ roc_npc_init(struct roc_npc *roc_npc)\n \t */\n \tplt_bitmap_set(npc->rss_grp_entries, 0);\n \n+\trc = npc_aged_flows_bitmap_alloc(roc_npc);\n+\tif (rc != 0)\n+\t\tgoto done;\n \treturn rc;\n \n done:\n@@ -610,6 +614,17 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t\tflow->mtr_id = act_mtr->mtr_id;\n \t\t\treq_act |= ROC_NPC_ACTION_TYPE_METER;\n \t\t\tbreak;\n+\t\tcase ROC_NPC_ACTION_TYPE_AGE:\n+\t\t\tif (flow->is_validate == true)\n+\t\t\t\tbreak;\n+\t\t\tplt_seqcount_init(&roc_npc->flow_age.seq_cnt);\n+\t\t\terrcode = npc_aging_ctrl_thread_create(roc_npc,\n+\t\t\t\t\t\t\t       actions->conf,\n+\t\t\t\t\t\t\t       flow);\n+\t\t\tif (errcode != 0)\n+\t\t\t\tgoto err_exit;\n+\t\t\treq_act |= ROC_NPC_ACTION_TYPE_AGE;\n+\t\t\tbreak;\n \t\tdefault:\n \t\t\terrcode = NPC_ERR_ACTION_NOTSUP;\n \t\t\tgoto err_exit;\n@@ -1485,6 +1500,9 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,\n \t\t}\n \t}\n \tTAILQ_INSERT_TAIL(list, flow, next);\n+\n+\tnpc_age_flow_list_entry_add(roc_npc, flow);\n+\n \treturn flow;\n \n set_rss_failed:\n@@ -1582,6 +1600,10 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)\n \n \tnpc_delete_prio_list_entry(npc, flow);\n \n+\tnpc_age_flow_list_entry_delete(roc_npc, flow);\n+\tif (roc_npc->flow_age.age_flow_refcnt == 0 && roc_npc->flow_age.aged_flows_poll_thread)\n+\t\tnpc_aging_ctrl_thread_destroy(roc_npc);\n+\n done:\n \tplt_free(flow);\n \treturn 0;\ndiff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h\nindex 07e6634aa7..8b8a2eb343 100644\n--- a/drivers/common/cnxk/roc_npc.h\n+++ b/drivers/common/cnxk/roc_npc.h\n@@ -180,6 +180,7 @@ enum roc_npc_action_type {\n \tROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT = (1 << 15),\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 };\n \n struct roc_npc_action {\n@@ -203,6 +204,13 @@ struct roc_npc_action_port_id {\n \tuint32_t id;\t\t/**< port ID. */\n };\n \n+struct roc_npc_action_age {\n+\tuint32_t timeout : 24; /**< Time in seconds. */\n+\tuint32_t reserved : 8; /**< Reserved, must be zero. */\n+\t/** The user flow context, NULL means the rte_flow pointer. */\n+\tvoid *context;\n+};\n+\n /**\n  * ESP Header\n  */\n@@ -295,6 +303,9 @@ struct roc_npc_flow {\n \tuint16_t match_id;\n \tuint8_t is_inline_dev;\n \tbool use_pre_alloc;\n+\tuint64_t timeout_cycles;\n+\tvoid *age_context;\n+\tuint32_t timeout;\n \n \tTAILQ_ENTRY(roc_npc_flow) next;\n };\n@@ -327,6 +338,19 @@ enum flow_vtag_cfg_dir { VTAG_TX, VTAG_RX };\n #define ROC_ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */\n #define ROC_ETHER_TYPE_QINQ 0x88A8 /**< IEEE 802.1ad QinQ tagging. */\n \n+struct roc_npc_flow_age {\n+\tplt_seqcount_t seq_cnt;\n+\tuint32_t aging_poll_freq;\n+\tuint32_t age_flow_refcnt;\n+\tuint32_t aged_flows_cnt;\n+\tuint32_t start_id;\n+\tuint32_t end_id;\n+\tpthread_t aged_flows_poll_thread;\n+\tstruct plt_bitmap *aged_flows;\n+\tvoid *age_mem;\n+\tbool aged_flows_get_thread_exit;\n+};\n+\n struct roc_npc {\n \tstruct roc_nix *roc_nix;\n \tuint8_t switch_header_type;\n@@ -349,11 +373,14 @@ struct roc_npc {\n \tbool is_sdp_mask_set;\n \tuint16_t sdp_channel;\n \tuint16_t sdp_channel_mask;\n+\tstruct roc_npc_flow_age flow_age;\n \n #define ROC_NPC_MEM_SZ (6 * 1024)\n \tuint8_t reserved[ROC_NPC_MEM_SZ];\n } __plt_cache_aligned;\n \n+#define ROC_NPC_AGE_POLL_FREQ_MIN 10\n+\n int __roc_api roc_npc_init(struct roc_npc *roc_npc);\n int __roc_api roc_npc_fini(struct roc_npc *roc_npc);\n const char *__roc_api roc_npc_profile_name_get(struct roc_npc *roc_npc);\n@@ -397,4 +424,5 @@ int __roc_api roc_npc_validate_portid_action(struct roc_npc *roc_npc_src,\n \t\t\t\t\t     struct roc_npc *roc_npc_dst);\n int __roc_api roc_npc_mcam_init(struct roc_npc *roc_npc, struct roc_npc_flow *flow, int mcam_id);\n int __roc_api roc_npc_mcam_move(struct roc_npc *roc_npc, uint16_t old_ent, uint16_t new_ent);\n+void *__roc_api roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id);\n #endif /* _ROC_NPC_H_ */\ndiff --git a/drivers/common/cnxk/roc_npc_aging.c b/drivers/common/cnxk/roc_npc_aging.c\nnew file mode 100644\nindex 0000000000..94126fe9fd\n--- /dev/null\n+++ b/drivers/common/cnxk/roc_npc_aging.c\n@@ -0,0 +1,315 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2023 Marvell.\n+ */\n+\n+#include \"roc_api.h\"\n+#include \"roc_priv.h\"\n+\n+int\n+npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc)\n+{\n+\tstruct roc_npc_flow_age *flow_age;\n+\tuint8_t *age_mem = NULL;\n+\tuint32_t bmap_sz;\n+\tint rc = 0;\n+\n+\tbmap_sz = plt_bitmap_get_memory_footprint(MCAM_ARR_ELEM_SZ *\n+\t\t\t\t\t\t  MCAM_ARR_SIZE);\n+\tage_mem = plt_zmalloc(bmap_sz, 0);\n+\tif (age_mem == NULL) {\n+\t\tplt_err(\"Bmap alloc failed\");\n+\t\trc = NPC_ERR_NO_MEM;\n+\t\tgoto done;\n+\t}\n+\n+\tflow_age = &roc_npc->flow_age;\n+\tflow_age->age_mem = age_mem;\n+\tflow_age->aged_flows = plt_bitmap_init(MCAM_ARR_ELEM_SZ * MCAM_ARR_SIZE,\n+\t\t\t\t\t       age_mem, bmap_sz);\n+\tif (!flow_age->aged_flows) {\n+\t\tplt_err(\"Bitmap init failed\");\n+\t\tplt_free(age_mem);\n+\t\trc = NPC_ERR_NO_MEM;\n+\t\tgoto done;\n+\t}\n+\n+\tflow_age->age_flow_refcnt = 0;\n+done:\n+\treturn rc;\n+}\n+\n+void\n+npc_aged_flows_bitmap_free(struct roc_npc *roc_npc)\n+{\n+\tstruct roc_npc_flow_age *flow_age;\n+\n+\tflow_age = &roc_npc->flow_age;\n+\tplt_bitmap_free(flow_age->aged_flows);\n+\tif (flow_age->age_mem)\n+\t\tplt_free(roc_npc->flow_age.age_mem);\n+}\n+\n+static void\n+check_timeout_cycles(struct roc_npc *roc_npc, uint32_t mcam_id)\n+{\n+\tstruct npc *npc = roc_npc_to_npc_priv(roc_npc);\n+\tstruct npc_age_flow_list_head *list;\n+\tstruct npc_age_flow_entry *fl_iter;\n+\tstruct roc_npc_flow_age *flow_age;\n+\tbool aging_enabled = false;\n+\n+\tflow_age = &roc_npc->flow_age;\n+\tlist = &npc->age_flow_list;\n+\tTAILQ_FOREACH(fl_iter, list, next) {\n+\t\tif (fl_iter->flow->mcam_id == mcam_id &&\n+\t\t    fl_iter->flow->timeout_cycles < rte_get_timer_cycles()) {\n+\t\t\t/* update bitmap */\n+\t\t\tplt_bitmap_set(flow_age->aged_flows, mcam_id);\n+\t\t\tif (!aging_enabled) {\n+\t\t\t\tflow_age->start_id = mcam_id;\n+\t\t\t\tflow_age->end_id = mcam_id;\n+\t\t\t\taging_enabled = true;\n+\t\t\t}\n+\t\t\tif (flow_age->start_id > mcam_id)\n+\t\t\t\tflow_age->start_id = mcam_id;\n+\t\t\telse if (flow_age->end_id < mcam_id)\n+\t\t\t\tflow_age->end_id = mcam_id;\n+\t\t\tflow_age->aged_flows_cnt += 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n+static void\n+update_timeout_cycles(struct roc_npc *roc_npc, uint32_t mcam_id)\n+{\n+\tstruct npc *npc = roc_npc_to_npc_priv(roc_npc);\n+\tstruct npc_age_flow_list_head *list;\n+\tstruct npc_age_flow_entry *fl_iter;\n+\n+\tlist = &npc->age_flow_list;\n+\tTAILQ_FOREACH(fl_iter, list, next) {\n+\t\tif (fl_iter->flow->mcam_id == mcam_id) {\n+\t\t\tfl_iter->flow->timeout_cycles = rte_get_timer_cycles() +\n+\t\t\t\tfl_iter->flow->timeout * rte_get_timer_hz();\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n+static int\n+npc_mcam_get_hit_status(struct npc *npc, uint64_t *mcam_ids, uint16_t start_id,\n+\t\t\tuint16_t end_id, uint64_t *hit_status, bool clear)\n+{\n+\tstruct npc_mcam_get_hit_status_req *req;\n+\tstruct npc_mcam_get_hit_status_rsp *rsp;\n+\tstruct mbox *mbox = mbox_get(npc->mbox);\n+\tuint8_t idx_start;\n+\tuint8_t idx_end;\n+\tint rc;\n+\tint i;\n+\n+\treq = mbox_alloc_msg_npc_mcam_get_hit_status(mbox);\n+\tif (req == NULL)\n+\t\treturn -ENOSPC;\n+\n+\tidx_start = start_id / MCAM_ARR_ELEM_SZ;\n+\tidx_end = end_id / MCAM_ARR_ELEM_SZ;\n+\n+\tfor (i = idx_start; i <= idx_end; i++)\n+\t\treq->mcam_ids[i] = mcam_ids[i];\n+\n+\treq->range_valid_mcam_ids_start = start_id;\n+\treq->range_valid_mcam_ids_end = end_id;\n+\treq->clear = clear;\n+\n+\trc = mbox_process_msg(mbox, (void *)&rsp);\n+\tif (rc)\n+\t\tgoto exit;\n+\n+\tfor (i = idx_start; i <= idx_end; i++)\n+\t\thit_status[i] = rsp->mcam_hit_status[i];\n+\n+\trc = 0;\n+exit:\n+\tmbox_put(mbox);\n+\treturn rc;\n+}\n+\n+void *\n+npc_aged_flows_get(void *args)\n+{\n+\tuint64_t hit_status[MCAM_ARR_SIZE] = {0};\n+\tuint64_t mcam_ids[MCAM_ARR_SIZE] = {0};\n+\tstruct npc_age_flow_list_head *list;\n+\tstruct npc_age_flow_entry *fl_iter;\n+\tstruct roc_npc *roc_npc = args;\n+\tstruct npc *npc = roc_npc_to_npc_priv(roc_npc);\n+\tstruct roc_npc_flow_age *flow_age;\n+\tbool aging_enabled;\n+\tuint32_t start_id;\n+\tuint32_t end_id;\n+\tuint32_t mcam_id;\n+\tuint32_t idx;\n+\tuint32_t i;\n+\tint rc;\n+\n+\tflow_age = &roc_npc->flow_age;\n+\tlist = &npc->age_flow_list;\n+\twhile (!flow_age->aged_flows_get_thread_exit) {\n+\t\tstart_id = 0;\n+\t\tend_id = 0;\n+\t\taging_enabled = false;\n+\t\tmemset(mcam_ids, 0, sizeof(mcam_ids));\n+\t\tTAILQ_FOREACH(fl_iter, list, next) {\n+\t\t\tmcam_id = fl_iter->flow->mcam_id;\n+\t\t\tidx = mcam_id / MCAM_ARR_ELEM_SZ;\n+\t\t\tmcam_ids[idx] |= BIT_ULL(mcam_id % MCAM_ARR_ELEM_SZ);\n+\n+\t\t\tif (!aging_enabled) {\n+\t\t\t\tstart_id = mcam_id;\n+\t\t\t\tend_id = mcam_id;\n+\t\t\t\taging_enabled = true;\n+\t\t\t}\n+\n+\t\t\tif (mcam_id < start_id)\n+\t\t\t\tstart_id = mcam_id;\n+\t\t\telse if (mcam_id > end_id)\n+\t\t\t\tend_id = mcam_id;\n+\t\t}\n+\n+\t\tif (!aging_enabled)\n+\t\t\tgoto lbl_sleep;\n+\n+\t\trc = npc_mcam_get_hit_status(npc, mcam_ids, start_id, end_id,\n+\t\t\t\t\t     hit_status, true);\n+\t\tif (rc)\n+\t\t\treturn NULL;\n+\n+\t\tplt_seqcount_write_begin(&flow_age->seq_cnt);\n+\t\tflow_age->aged_flows_cnt = 0;\n+\t\tfor (i = start_id; i <= end_id; i++) {\n+\t\t\tidx = i / MCAM_ARR_ELEM_SZ;\n+\t\t\tif (mcam_ids[idx] & BIT_ULL(i % MCAM_ARR_ELEM_SZ)) {\n+\t\t\t\tif (!(hit_status[idx] & BIT_ULL(i % MCAM_ARR_ELEM_SZ)))\n+\t\t\t\t\tcheck_timeout_cycles(roc_npc, i);\n+\t\t\t\telse\n+\t\t\t\t\tupdate_timeout_cycles(roc_npc, i);\n+\t\t\t}\n+\t\t}\n+\t\tplt_seqcount_write_end(&flow_age->seq_cnt);\n+\n+lbl_sleep:\n+\t\tsleep(flow_age->aging_poll_freq);\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+void\n+npc_age_flow_list_entry_add(struct roc_npc *roc_npc, struct roc_npc_flow *flow)\n+{\n+\tstruct npc *npc = roc_npc_to_npc_priv(roc_npc);\n+\tstruct npc_age_flow_entry *age_fl_iter;\n+\tstruct npc_age_flow_entry *new_entry;\n+\n+\tnew_entry = plt_zmalloc(sizeof(*new_entry), 0);\n+\tnew_entry->flow = flow;\n+\troc_npc->flow_age.age_flow_refcnt++;\n+\t/* List in ascending order of mcam entries */\n+\tTAILQ_FOREACH(age_fl_iter, &npc->age_flow_list, next) {\n+\t\tif (age_fl_iter->flow->mcam_id > flow->mcam_id) {\n+\t\t\tTAILQ_INSERT_BEFORE(age_fl_iter, new_entry, next);\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\tTAILQ_INSERT_TAIL(&npc->age_flow_list, new_entry, next);\n+}\n+\n+void\n+npc_age_flow_list_entry_delete(struct roc_npc *roc_npc,\n+\t\t\t       struct roc_npc_flow *flow)\n+{\n+\tstruct npc *npc = roc_npc_to_npc_priv(roc_npc);\n+\tstruct npc_age_flow_list_head *list;\n+\tstruct npc_age_flow_entry *curr;\n+\n+\tlist = &npc->age_flow_list;\n+\tcurr = TAILQ_FIRST(list);\n+\n+\tif (!curr)\n+\t\treturn;\n+\n+\twhile (curr) {\n+\t\tif (flow->mcam_id == curr->flow->mcam_id) {\n+\t\t\tTAILQ_REMOVE(list, curr, next);\n+\t\t\tplt_free(curr);\n+\t\t\tbreak;\n+\t\t}\n+\t\tcurr = TAILQ_NEXT(curr, next);\n+\t}\n+\troc_npc->flow_age.age_flow_refcnt--;\n+}\n+\n+int\n+npc_aging_ctrl_thread_create(struct roc_npc *roc_npc,\n+\t\t\t     const struct roc_npc_action_age *age,\n+\t\t\t     struct roc_npc_flow *flow)\n+{\n+\tstruct roc_npc_flow_age *flow_age;\n+\tint errcode = 0;\n+\n+\tflow_age = &roc_npc->flow_age;\n+\tif (age->timeout < flow_age->aging_poll_freq) {\n+\t\tplt_err(\"Age timeout should be greater or equal to %u seconds\",\n+\t\t\tflow_age->aging_poll_freq);\n+\t\terrcode = NPC_ERR_ACTION_NOTSUP;\n+\t\tgoto done;\n+\t}\n+\n+\tflow->age_context = age->context == NULL ? flow : age->context;\n+\tflow->timeout = age->timeout;\n+\tflow->timeout_cycles = rte_get_timer_cycles() + age->timeout *\n+\t\t\t       rte_get_timer_hz();\n+\n+\tif (flow_age->age_flow_refcnt == 0) {\n+\t\tflow_age->aged_flows_get_thread_exit = false;\n+\t\tif (plt_ctrl_thread_create(&flow_age->aged_flows_poll_thread,\n+\t\t\t\t\t   \"Aged Flows Get Ctrl Thread\", NULL,\n+\t\t\t\t\t   npc_aged_flows_get, roc_npc) != 0) {\n+\t\t\tplt_err(\"Failed to create thread for age flows\");\n+\t\t\terrcode = NPC_ERR_ACTION_NOTSUP;\n+\t\t\tgoto done;\n+\t\t}\n+\t}\n+done:\n+\treturn errcode;\n+}\n+\n+void\n+npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc)\n+{\n+\tstruct roc_npc_flow_age *flow_age;\n+\n+\tflow_age = &roc_npc->flow_age;\n+\tflow_age->aged_flows_get_thread_exit = true;\n+\tpthread_join(flow_age->aged_flows_poll_thread, NULL);\n+\tnpc_aged_flows_bitmap_free(roc_npc);\n+}\n+\n+void *\n+roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id)\n+{\n+\tstruct npc *npc = roc_npc_to_npc_priv(roc_npc);\n+\tstruct npc_age_flow_list_head *list;\n+\tstruct npc_age_flow_entry *fl_iter;\n+\n+\tlist = &npc->age_flow_list;\n+\n+\tTAILQ_FOREACH(fl_iter, list, next) {\n+\t\tif (fl_iter->flow->mcam_id == mcam_id)\n+\t\t\treturn fl_iter->flow->age_context;\n+\t}\n+\n+\treturn NULL;\n+}\ndiff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h\nindex 593dca353b..6d6cb64c65 100644\n--- a/drivers/common/cnxk/roc_npc_priv.h\n+++ b/drivers/common/cnxk/roc_npc_priv.h\n@@ -378,6 +378,13 @@ struct npc_prio_flow_entry {\n \n TAILQ_HEAD(npc_prio_flow_list_head, npc_prio_flow_entry);\n \n+struct npc_age_flow_entry {\n+\tstruct roc_npc_flow *flow;\n+\tTAILQ_ENTRY(npc_age_flow_entry) next;\n+};\n+\n+TAILQ_HEAD(npc_age_flow_list_head, npc_age_flow_entry);\n+\n struct npc {\n \tstruct mbox *mbox;\t\t\t/* Mbox */\n \tuint32_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */\n@@ -403,6 +410,7 @@ struct npc {\n \tnpc_ld_flags_t prx_lfcfg;    /* KEX LD_Flags CFG */\n \tstruct npc_flow_list *flow_list;\n \tstruct npc_prio_flow_list_head *prio_flow_list;\n+\tstruct npc_age_flow_list_head age_flow_list;\n \tstruct plt_bitmap *rss_grp_entries;\n \tstruct npc_flow_list ipsec_list;\n \tuint8_t exact_match_ena;\n@@ -480,4 +488,13 @@ int npc_rss_action_program(struct roc_npc *roc_npc, const struct roc_npc_action\n int npc_rss_group_free(struct npc *npc, struct roc_npc_flow *flow);\n int npc_mcam_init(struct npc *npc, struct roc_npc_flow *flow, int mcam_id);\n int npc_mcam_move(struct mbox *mbox, uint16_t old_ent, uint16_t new_ent);\n+void npc_age_flow_list_entry_add(struct roc_npc *npc, struct roc_npc_flow *flow);\n+void npc_age_flow_list_entry_delete(struct roc_npc *npc, struct roc_npc_flow *flow);\n+void *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+\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/roc_platform.h b/drivers/common/cnxk/roc_platform.h\nindex 9884398a99..e7a6564163 100644\n--- a/drivers/common/cnxk/roc_platform.h\n+++ b/drivers/common/cnxk/roc_platform.h\n@@ -20,6 +20,7 @@\n #include <rte_malloc.h>\n #include <rte_memzone.h>\n #include <rte_pci.h>\n+#include <rte_seqcount.h>\n #include <rte_spinlock.h>\n #include <rte_string_fns.h>\n #include <rte_tailq.h>\n@@ -130,6 +131,13 @@\n #define plt_spinlock_unlock  rte_spinlock_unlock\n #define plt_spinlock_trylock rte_spinlock_trylock\n \n+#define plt_seqcount_t\t\t\trte_seqcount_t\n+#define plt_seqcount_init\t\trte_seqcount_init\n+#define plt_seqcount_read_begin\t\trte_seqcount_read_begin\n+#define plt_seqcount_read_retry\t\trte_seqcount_read_retry\n+#define plt_seqcount_write_begin\trte_seqcount_write_begin\n+#define plt_seqcount_write_end\t\trte_seqcount_write_end\n+\n #define plt_intr_callback_register   rte_intr_callback_register\n #define plt_intr_callback_unregister rte_intr_callback_unregister\n #define plt_intr_disable\t     rte_intr_disable\ndiff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map\nindex 8c71497df8..28f0f55934 100644\n--- a/drivers/common/cnxk/version.map\n+++ b/drivers/common/cnxk/version.map\n@@ -425,6 +425,7 @@ INTERNAL {\n \troc_npa_pool_op_range_set;\n \troc_npa_pool_range_update_check;\n \troc_npa_zero_aura_handle;\n+\troc_npc_aged_flow_ctx_get;\n \troc_npc_fini;\n \troc_npc_flow_create;\n \troc_npc_flow_destroy;\n",
    "prefixes": [
        "v1",
        "1/2"
    ]
}