get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 136269,
    "url": "http://patches.dpdk.org/api/patches/136269/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20240201130754.194352-11-hkalra@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": "<20240201130754.194352-11-hkalra@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20240201130754.194352-11-hkalra@marvell.com",
    "date": "2024-02-01T13:07:41",
    "name": "[v3,10/23] net/cnxk: add representor control plane",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "fb0483629cd8b55f2f45b7b63d4326a19f26355c",
    "submitter": {
        "id": 1182,
        "url": "http://patches.dpdk.org/api/people/1182/?format=api",
        "name": "Harman Kalra",
        "email": "hkalra@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/20240201130754.194352-11-hkalra@marvell.com/mbox/",
    "series": [
        {
            "id": 30966,
            "url": "http://patches.dpdk.org/api/series/30966/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=30966",
            "date": "2024-02-01T13:07:31",
            "name": "net/cnxk: support for port representors",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/30966/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/136269/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/136269/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 2A95543A3A;\n\tThu,  1 Feb 2024 14:09:48 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 0A82242E50;\n\tThu,  1 Feb 2024 14:08:52 +0100 (CET)",
            "from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com\n [67.231.156.173])\n by mails.dpdk.org (Postfix) with ESMTP id 5CD8D42E4B\n for <dev@dpdk.org>; Thu,  1 Feb 2024 14:08:50 +0100 (CET)",
            "from pps.filterd (m0045851.ppops.net [127.0.0.1])\n by mx0b-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id\n 4119trhC001728 for <dev@dpdk.org>; Thu, 1 Feb 2024 05:08:49 -0800",
            "from dc5-exch02.marvell.com ([199.233.59.182])\n by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3w0937ghcf-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)\n for <dev@dpdk.org>; Thu, 01 Feb 2024 05:08:49 -0800 (PST)",
            "from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48;\n Thu, 1 Feb 2024 05:08:47 -0800",
            "from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com\n (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend\n Transport; Thu, 1 Feb 2024 05:08:47 -0800",
            "from localhost.localdomain (unknown [10.29.52.211])\n by maili.marvell.com (Postfix) with ESMTP id DB1303F707A;\n Thu,  1 Feb 2024 05:08:44 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=\n from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-type; s=pfpt0220; bh=6Y4dCZ8OgWb92siTUJWKh\n XPEnPJizXZfdzqBxlRkBz8=; b=HEdHipE8y0+NMvRohMKTVmsjx8azOX4R0G4k1\n /yGEp2S8zl7Dr8rnbHzMRdXoqBgNY30OBmbUJ4OcsMoS4Mf2s6ZanpQA3S82l/Py\n mfkG5PCrPA9RZRnt1KUll1oTmnZpqES2RhZuFRmjqF2PYMG4tZ+iYIxCGOhPrEYg\n kAnGYcl1GGonBrzzGjwtJFwfuXZhZ9wSUsBTyQVzx8uoiNbpI7lmzepcM9d0inmc\n zWd6LM23YXIlT9lnaE5+dTSwjD0oGLkn0En4i3m2sFeHlECipYLwVjtny26m1xDy\n VT6cpnEmXgfY0XrGfaPGeU3uYEXiwlzOsZ4M8N3shNNyP+HUA==",
        "From": "Harman Kalra <hkalra@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>, Harman Kalra <hkalra@marvell.com>",
        "CC": "<dev@dpdk.org>",
        "Subject": "[PATCH v3 10/23] net/cnxk: add representor control plane",
        "Date": "Thu, 1 Feb 2024 18:37:41 +0530",
        "Message-ID": "<20240201130754.194352-11-hkalra@marvell.com>",
        "X-Mailer": "git-send-email 2.18.0",
        "In-Reply-To": "<20240201130754.194352-1-hkalra@marvell.com>",
        "References": "<20230811163419.165790-1-hkalra@marvell.com>\n <20240201130754.194352-1-hkalra@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Proofpoint-ORIG-GUID": "_fF_FisL2exeM3u9sNoOaPbD0SIMYdLc",
        "X-Proofpoint-GUID": "_fF_FisL2exeM3u9sNoOaPbD0SIMYdLc",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26\n definitions=2024-02-01_02,2024-01-31_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": "Implementing the control path for representor ports, where represented\nports can be configured using TLV messaging.\n\nSigned-off-by: Harman Kalra <hkalra@marvell.com>\n---\n drivers/net/cnxk/cnxk_eswitch.c |  70 ++-\n drivers/net/cnxk/cnxk_eswitch.h |   8 +\n drivers/net/cnxk/cnxk_rep.c     |  52 ++\n drivers/net/cnxk/cnxk_rep.h     |   3 +\n drivers/net/cnxk/cnxk_rep_msg.c | 827 ++++++++++++++++++++++++++++++++\n drivers/net/cnxk/cnxk_rep_msg.h |  95 ++++\n drivers/net/cnxk/meson.build    |   1 +\n 7 files changed, 1048 insertions(+), 8 deletions(-)\n create mode 100644 drivers/net/cnxk/cnxk_rep_msg.c\n create mode 100644 drivers/net/cnxk/cnxk_rep_msg.h",
    "diff": "diff --git a/drivers/net/cnxk/cnxk_eswitch.c b/drivers/net/cnxk/cnxk_eswitch.c\nindex 6f651e0857..ad6834410d 100644\n--- a/drivers/net/cnxk/cnxk_eswitch.c\n+++ b/drivers/net/cnxk/cnxk_eswitch.c\n@@ -9,6 +9,27 @@\n \n #define CNXK_NIX_DEF_SQ_COUNT 512\n \n+int\n+cnxk_eswitch_representor_id(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func,\n+\t\t\t    uint16_t *rep_id)\n+{\n+\tstruct cnxk_esw_repr_hw_info *repr_info;\n+\tint rc = 0;\n+\n+\trepr_info = cnxk_eswitch_representor_hw_info(eswitch_dev, hw_func);\n+\tif (!repr_info) {\n+\t\tplt_warn(\"Failed to get representor group for %x\", hw_func);\n+\t\trc = -ENOENT;\n+\t\tgoto fail;\n+\t}\n+\n+\t*rep_id = repr_info->rep_id;\n+\n+\treturn 0;\n+fail:\n+\treturn rc;\n+}\n+\n struct cnxk_esw_repr_hw_info *\n cnxk_eswitch_representor_hw_info(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func)\n {\n@@ -86,8 +107,41 @@ cnxk_eswitch_dev_remove(struct rte_pci_device *pci_dev)\n \t}\n \n \t/* Remove representor devices associated with PF */\n-\tif (eswitch_dev->repr_cnt.nb_repr_created)\n+\tif (eswitch_dev->repr_cnt.nb_repr_created) {\n+\t\t/* Exiting the rep msg ctrl thread */\n+\t\tif (eswitch_dev->start_ctrl_msg_thrd) {\n+\t\t\tuint32_t sunlen;\n+\t\t\tstruct sockaddr_un sun = {0};\n+\t\t\tint sock_fd = 0;\n+\n+\t\t\teswitch_dev->start_ctrl_msg_thrd = false;\n+\t\t\tif (!eswitch_dev->client_connected) {\n+\t\t\t\tplt_esw_dbg(\"Establishing connection for teardown\");\n+\t\t\t\tsock_fd = socket(AF_UNIX, SOCK_STREAM, 0);\n+\t\t\t\tif (sock_fd == -1) {\n+\t\t\t\t\tplt_err(\"Failed to open socket. err %d\", -errno);\n+\t\t\t\t\treturn -errno;\n+\t\t\t\t}\n+\t\t\t\tsun.sun_family = AF_UNIX;\n+\t\t\t\tsunlen = sizeof(struct sockaddr_un);\n+\t\t\t\tstrncpy(sun.sun_path, CNXK_ESWITCH_CTRL_MSG_SOCK_PATH,\n+\t\t\t\t\tsizeof(sun.sun_path) - 1);\n+\n+\t\t\t\tif (connect(sock_fd, (struct sockaddr *)&sun, sunlen) < 0) {\n+\t\t\t\t\tplt_err(\"Failed to connect socket: %s, err %d\",\n+\t\t\t\t\t\tCNXK_ESWITCH_CTRL_MSG_SOCK_PATH, errno);\n+\t\t\t\t\tclose(sock_fd);\n+\t\t\t\t\treturn -errno;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\trte_thread_join(eswitch_dev->rep_ctrl_msg_thread, NULL);\n+\t\t\tif (!eswitch_dev->client_connected)\n+\t\t\t\tclose(sock_fd);\n+\t\t}\n+\n+\t\t/* Remove representor devices associated with PF */\n \t\tcnxk_rep_dev_remove(eswitch_dev);\n+\t}\n \n \t/* Cleanup NPC rxtx flow rules */\n \tcnxk_eswitch_flow_rules_remove_list(eswitch_dev, &eswitch_dev->esw_flow_list,\n@@ -106,13 +160,6 @@ cnxk_eswitch_nix_rsrc_start(struct cnxk_eswitch_dev *eswitch_dev)\n {\n \tint rc;\n \n-\t/* Enable Rx in NPC */\n-\trc = roc_nix_npc_rx_ena_dis(&eswitch_dev->nix, true);\n-\tif (rc) {\n-\t\tplt_err(\"Failed to enable NPC rx %d\", rc);\n-\t\tgoto done;\n-\t}\n-\n \t/* Install eswitch PF mcam rules */\n \trc = cnxk_eswitch_pfvf_flow_rules_install(eswitch_dev, false);\n \tif (rc) {\n@@ -128,6 +175,13 @@ cnxk_eswitch_nix_rsrc_start(struct cnxk_eswitch_dev *eswitch_dev)\n \t\tgoto done;\n \t}\n \n+\t/* Enable Rx in NPC */\n+\trc = roc_nix_npc_rx_ena_dis(&eswitch_dev->nix, true);\n+\tif (rc) {\n+\t\tplt_err(\"Failed to enable NPC rx %d\", rc);\n+\t\tgoto done;\n+\t}\n+\n \trc = roc_npc_mcam_enable_all_entries(&eswitch_dev->npc, 1);\n \tif (rc) {\n \t\tplt_err(\"Failed to enable NPC entries %d\", rc);\ndiff --git a/drivers/net/cnxk/cnxk_eswitch.h b/drivers/net/cnxk/cnxk_eswitch.h\nindex 4edfa91bdc..ecf10a8e08 100644\n--- a/drivers/net/cnxk/cnxk_eswitch.h\n+++ b/drivers/net/cnxk/cnxk_eswitch.h\n@@ -133,6 +133,12 @@ struct cnxk_eswitch_dev {\n \t/* No of representors */\n \tstruct cnxk_eswitch_repr_cnt repr_cnt;\n \n+\t/* Representor control channel field */\n+\tbool start_ctrl_msg_thrd;\n+\trte_thread_t rep_ctrl_msg_thread;\n+\tbool client_connected;\n+\tint sock_fd;\n+\n \t/* Port representor fields */\n \trte_spinlock_t rep_lock;\n \tuint16_t nb_switch_domain;\n@@ -155,6 +161,8 @@ cnxk_eswitch_pmd_priv(void)\n \n /* HW Resources */\n int cnxk_eswitch_nix_rsrc_start(struct cnxk_eswitch_dev *eswitch_dev);\n+int cnxk_eswitch_representor_id(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func,\n+\t\t\t\tuint16_t *rep_id);\n struct cnxk_esw_repr_hw_info *cnxk_eswitch_representor_hw_info(struct cnxk_eswitch_dev *eswitch_dev,\n \t\t\t\t\t\t\t       uint16_t hw_func);\n int cnxk_eswitch_repr_devargs(struct rte_pci_device *pci_dev, struct cnxk_eswitch_dev *eswitch_dev);\ndiff --git a/drivers/net/cnxk/cnxk_rep.c b/drivers/net/cnxk/cnxk_rep.c\nindex 55156f5b56..5b619ebb9e 100644\n--- a/drivers/net/cnxk/cnxk_rep.c\n+++ b/drivers/net/cnxk/cnxk_rep.c\n@@ -2,6 +2,7 @@\n  * Copyright(C) 2024 Marvell.\n  */\n #include <cnxk_rep.h>\n+#include <cnxk_rep_msg.h>\n \n #define PF_SHIFT 10\n #define PF_MASK\t 0x3F\n@@ -25,6 +26,48 @@ switch_domain_id_allocate(struct cnxk_eswitch_dev *eswitch_dev, uint16_t pf)\n \treturn RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;\n }\n \n+int\n+cnxk_rep_state_update(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func, uint16_t *rep_id)\n+{\n+\tstruct cnxk_rep_dev *rep_dev = NULL;\n+\tstruct rte_eth_dev *rep_eth_dev;\n+\tint i, rc = 0;\n+\n+\t/* Delete the individual PFVF flows as common eswitch VF rule will be used. */\n+\trc = cnxk_eswitch_flow_rules_delete(eswitch_dev, hw_func);\n+\tif (rc) {\n+\t\tif (rc != -ENOENT) {\n+\t\t\tplt_err(\"Failed to delete %x flow rules\", hw_func);\n+\t\t\tgoto fail;\n+\t\t}\n+\t}\n+\t/* Rep ID for respective HW func */\n+\trc = cnxk_eswitch_representor_id(eswitch_dev, hw_func, rep_id);\n+\tif (rc) {\n+\t\tif (rc != -ENOENT) {\n+\t\t\tplt_err(\"Failed to get rep info for %x\", hw_func);\n+\t\t\tgoto fail;\n+\t\t}\n+\t}\n+\t/* Update the state - representee is standalone or part of companian app */\n+\tfor (i = 0; i < eswitch_dev->repr_cnt.nb_repr_probed; i++) {\n+\t\trep_eth_dev = eswitch_dev->rep_info[i].rep_eth_dev;\n+\t\tif (!rep_eth_dev) {\n+\t\t\tplt_err(\"Failed to get rep ethdev handle\");\n+\t\t\trc = -EINVAL;\n+\t\t\tgoto fail;\n+\t\t}\n+\n+\t\trep_dev = cnxk_rep_pmd_priv(rep_eth_dev);\n+\t\tif (rep_dev->hw_func == hw_func && rep_dev->is_vf_active)\n+\t\t\trep_dev->native_repte = false;\n+\t}\n+\n+\treturn 0;\n+fail:\n+\treturn rc;\n+}\n+\n int\n cnxk_rep_dev_uninit(struct rte_eth_dev *ethdev)\n {\n@@ -250,6 +293,15 @@ cnxk_rep_dev_probe(struct rte_pci_device *pci_dev, struct cnxk_eswitch_dev *eswi\n \t}\n \teswitch_dev->last_probed = i;\n \n+\t/* Launch a thread to handle control messages */\n+\tif (!eswitch_dev->start_ctrl_msg_thrd) {\n+\t\trc = cnxk_rep_msg_control_thread_launch(eswitch_dev);\n+\t\tif (rc) {\n+\t\t\tplt_err(\"Failed to launch message ctrl thread\");\n+\t\t\tgoto fail;\n+\t\t}\n+\t}\n+\n \treturn 0;\n fail:\n \treturn rc;\ndiff --git a/drivers/net/cnxk/cnxk_rep.h b/drivers/net/cnxk/cnxk_rep.h\nindex b802c44b33..da298823a7 100644\n--- a/drivers/net/cnxk/cnxk_rep.h\n+++ b/drivers/net/cnxk/cnxk_rep.h\n@@ -16,6 +16,8 @@ struct cnxk_rep_dev {\n \tuint16_t switch_domain_id;\n \tstruct cnxk_eswitch_dev *parent_dev;\n \tuint16_t hw_func;\n+\tbool is_vf_active;\n+\tbool native_repte;\n \tuint8_t mac_addr[RTE_ETHER_ADDR_LEN];\n };\n \n@@ -46,5 +48,6 @@ int cnxk_rep_dev_close(struct rte_eth_dev *eth_dev);\n int cnxk_rep_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats);\n int cnxk_rep_stats_reset(struct rte_eth_dev *eth_dev);\n int cnxk_rep_flow_ops_get(struct rte_eth_dev *ethdev, const struct rte_flow_ops **ops);\n+int cnxk_rep_state_update(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func, uint16_t *rep_id);\n \n #endif /* __CNXK_REP_H__ */\ndiff --git a/drivers/net/cnxk/cnxk_rep_msg.c b/drivers/net/cnxk/cnxk_rep_msg.c\nnew file mode 100644\nindex 0000000000..0af87f0169\n--- /dev/null\n+++ b/drivers/net/cnxk/cnxk_rep_msg.c\n@@ -0,0 +1,827 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2024 Marvell.\n+ */\n+\n+#include <cnxk_rep.h>\n+#include <cnxk_rep_msg.h>\n+\n+#define CTRL_MSG_RCV_TIMEOUT_MS 2000\n+#define CTRL_MSG_READY_WAIT_US\t2000\n+#define CTRL_MSG_THRD_NAME_LEN\t35\n+#define CTRL_MSG_BUFFER_SZ\t1500\n+#define CTRL_MSG_SIGNATURE\t0xcdacdeadbeefcadc\n+\n+static void\n+close_socket(int fd)\n+{\n+\tclose(fd);\n+\tunlink(CNXK_ESWITCH_CTRL_MSG_SOCK_PATH);\n+}\n+\n+static int\n+receive_control_message(int socketfd, void *data, uint32_t len)\n+{\n+\tchar ctl[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred))] = {0};\n+\tstruct ucred *cr __rte_unused;\n+\tstruct msghdr mh = {0};\n+\tstruct cmsghdr *cmsg;\n+\tstatic uint64_t rec;\n+\tstruct iovec iov[1];\n+\tssize_t size;\n+\tint afd = -1;\n+\n+\tiov[0].iov_base = data;\n+\tiov[0].iov_len = len;\n+\tmh.msg_iov = iov;\n+\tmh.msg_iovlen = 1;\n+\tmh.msg_control = ctl;\n+\tmh.msg_controllen = sizeof(ctl);\n+\n+\tsize = recvmsg(socketfd, &mh, MSG_DONTWAIT);\n+\tif (size < 0) {\n+\t\tif (errno == EAGAIN)\n+\t\t\treturn 0;\n+\t\tplt_err(\"recvmsg err %d size %ld\", errno, size);\n+\t\treturn -errno;\n+\t} else if (size == 0) {\n+\t\treturn 0;\n+\t}\n+\n+\trec++;\n+\tplt_rep_dbg(\"Packet %\" PRId64 \" Received %\" PRId64 \" bytes over socketfd %d\",\n+\t\t    rec, size, socketfd);\n+\n+\tcr = 0;\n+\tcmsg = CMSG_FIRSTHDR(&mh);\n+\twhile (cmsg) {\n+\t\tif (cmsg->cmsg_level == SOL_SOCKET) {\n+\t\t\tif (cmsg->cmsg_type == SCM_CREDENTIALS) {\n+\t\t\t\tcr = (struct ucred *)CMSG_DATA(cmsg);\n+\t\t\t} else if (cmsg->cmsg_type == SCM_RIGHTS) {\n+\t\t\t\trte_memcpy(&afd, CMSG_DATA(cmsg), sizeof(int));\n+\t\t\t\tplt_rep_dbg(\"afd %d\", afd);\n+\t\t\t}\n+\t\t}\n+\t\tcmsg = CMSG_NXTHDR(&mh, cmsg);\n+\t}\n+\treturn size;\n+}\n+\n+static int\n+send_message_on_socket(int socketfd, void *data, uint32_t len, int afd)\n+{\n+\tchar ctl[CMSG_SPACE(sizeof(int))];\n+\tstruct msghdr mh = {0};\n+\tstruct cmsghdr *cmsg;\n+\tstatic uint64_t sent;\n+\tstruct iovec iov[1];\n+\tint size;\n+\n+\tiov[0].iov_base = data;\n+\tiov[0].iov_len = len;\n+\tmh.msg_iov = iov;\n+\tmh.msg_iovlen = 1;\n+\n+\tif (afd > 0) {\n+\t\tmemset(&ctl, 0, sizeof(ctl));\n+\t\tmh.msg_control = ctl;\n+\t\tmh.msg_controllen = sizeof(ctl);\n+\t\tcmsg = CMSG_FIRSTHDR(&mh);\n+\t\tcmsg->cmsg_len = CMSG_LEN(sizeof(int));\n+\t\tcmsg->cmsg_level = SOL_SOCKET;\n+\t\tcmsg->cmsg_type = SCM_RIGHTS;\n+\t\trte_memcpy(CMSG_DATA(cmsg), &afd, sizeof(int));\n+\t}\n+\n+\tsize = sendmsg(socketfd, &mh, MSG_DONTWAIT);\n+\tif (size < 0) {\n+\t\tif (errno == EAGAIN)\n+\t\t\treturn 0;\n+\t\tplt_err(\"Failed to send message, err %d\", -errno);\n+\t\treturn -errno;\n+\t} else if (size == 0) {\n+\t\treturn 0;\n+\t}\n+\tsent++;\n+\tplt_rep_dbg(\"Sent %\" PRId64 \" packets of size %d on socketfd %d\", sent, size, socketfd);\n+\n+\treturn size;\n+}\n+\n+static int\n+open_socket_ctrl_channel(void)\n+{\n+\tstruct sockaddr_un un;\n+\tint sock_fd;\n+\n+\tsock_fd = socket(AF_UNIX, SOCK_STREAM, 0);\n+\tif (sock_fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"failed to create unix socket\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* Set unix socket path and bind */\n+\tmemset(&un, 0, sizeof(un));\n+\tun.sun_family = AF_UNIX;\n+\n+\tif (strlen(CNXK_ESWITCH_CTRL_MSG_SOCK_PATH) > sizeof(un.sun_path) - 1) {\n+\t\tplt_err(\"Server socket path too long: %s\", CNXK_ESWITCH_CTRL_MSG_SOCK_PATH);\n+\t\tclose(sock_fd);\n+\t\treturn -E2BIG;\n+\t}\n+\n+\tif (remove(CNXK_ESWITCH_CTRL_MSG_SOCK_PATH) == -1 && errno != ENOENT) {\n+\t\tplt_err(\"remove-%s\", CNXK_ESWITCH_CTRL_MSG_SOCK_PATH);\n+\t\tclose(sock_fd);\n+\t\treturn -errno;\n+\t}\n+\n+\tmemset(&un, 0, sizeof(struct sockaddr_un));\n+\tun.sun_family = AF_UNIX;\n+\tstrncpy(un.sun_path, CNXK_ESWITCH_CTRL_MSG_SOCK_PATH, sizeof(un.sun_path) - 1);\n+\n+\tif (bind(sock_fd, (struct sockaddr *)&un, sizeof(un)) < 0) {\n+\t\tplt_err(\"Failed to bind %s: %s\", un.sun_path, strerror(errno));\n+\t\tclose(sock_fd);\n+\t\treturn -errno;\n+\t}\n+\n+\tif (listen(sock_fd, 1) < 0) {\n+\t\tplt_err(\"Failed to listen, err %s\", strerror(errno));\n+\t\tclose(sock_fd);\n+\t\treturn -errno;\n+\t}\n+\n+\tplt_rep_dbg(\"Unix socket path %s\", un.sun_path);\n+\treturn sock_fd;\n+}\n+\n+static int\n+send_control_message(struct cnxk_eswitch_dev *eswitch_dev, void *buffer, uint32_t len)\n+{\n+\tint sz;\n+\tint rc = 0;\n+\n+\tsz = send_message_on_socket(eswitch_dev->sock_fd, buffer, len, 0);\n+\tif (sz < 0) {\n+\t\tplt_err(\"Error sending message, err %d\", sz);\n+\t\trc = sz;\n+\t\tgoto done;\n+\t}\n+\n+\t/* Ensuring entire message has been processed */\n+\tif (sz != (int)len) {\n+\t\tplt_err(\"Out of %d bytes only %d bytes sent\", sz, len);\n+\t\trc = -EFAULT;\n+\t\tgoto done;\n+\t}\n+\tplt_rep_dbg(\"Sent %d bytes of buffer\", sz);\n+done:\n+\treturn rc;\n+}\n+\n+void\n+cnxk_rep_msg_populate_msg_end(void *buffer, uint32_t *length)\n+{\n+\tcnxk_rep_msg_populate_command(buffer, length, CNXK_REP_MSG_END, 0);\n+}\n+\n+void\n+cnxk_rep_msg_populate_type(void *buffer, uint32_t *length, cnxk_type_t type, uint32_t sz)\n+{\n+\tuint32_t len = *length;\n+\tcnxk_type_data_t data;\n+\n+\tmemset(&data, 0, sizeof(cnxk_type_data_t));\n+\t/* Prepare type data */\n+\tdata.type = type;\n+\tdata.length = sz;\n+\n+\t/* Populate the type data */\n+\trte_memcpy(RTE_PTR_ADD(buffer, len), &data, sizeof(cnxk_type_data_t));\n+\tlen += sizeof(cnxk_type_data_t);\n+\n+\t*length = len;\n+}\n+\n+void\n+cnxk_rep_msg_populate_header(void *buffer, uint32_t *length)\n+{\n+\tcnxk_header_t hdr;\n+\tint len;\n+\n+\tcnxk_rep_msg_populate_type(buffer, length, CNXK_TYPE_HEADER, sizeof(cnxk_header_t));\n+\n+\tmemset(&hdr, 0, sizeof(cnxk_header_t));\n+\tlen = *length;\n+\t/* Prepare header data */\n+\thdr.signature = CTRL_MSG_SIGNATURE;\n+\n+\t/* Populate header data */\n+\trte_memcpy(RTE_PTR_ADD(buffer, len), &hdr, sizeof(cnxk_header_t));\n+\tlen += sizeof(cnxk_header_t);\n+\n+\t*length = len;\n+}\n+\n+void\n+cnxk_rep_msg_populate_command(void *buffer, uint32_t *length, cnxk_rep_msg_t type, uint32_t size)\n+{\n+\tcnxk_rep_msg_data_t msg_data;\n+\tuint32_t len;\n+\tuint16_t sz = sizeof(cnxk_rep_msg_data_t);\n+\n+\tmemset(&msg_data, 0, sz);\n+\tcnxk_rep_msg_populate_type(buffer, length, CNXK_TYPE_MSG, sz);\n+\n+\tlen = *length;\n+\t/* Prepare command data */\n+\tmsg_data.type = type;\n+\tmsg_data.length = size;\n+\n+\t/* Populate the command */\n+\trte_memcpy(RTE_PTR_ADD(buffer, len), &msg_data, sz);\n+\tlen += sz;\n+\n+\t*length = len;\n+}\n+\n+void\n+cnxk_rep_msg_populate_command_meta(void *buffer, uint32_t *length, void *msg_meta, uint32_t sz,\n+\t\t\t\t   cnxk_rep_msg_t msg)\n+{\n+\tuint32_t len;\n+\n+\tcnxk_rep_msg_populate_command(buffer, length, msg, sz);\n+\n+\tlen = *length;\n+\t/* Populate command data */\n+\trte_memcpy(RTE_PTR_ADD(buffer, len), msg_meta, sz);\n+\tlen += sz;\n+\n+\t*length = len;\n+}\n+\n+static int\n+parse_validate_header(void *msg_buf, uint32_t *buf_trav_len)\n+{\n+\tcnxk_type_data_t *tdata = NULL;\n+\tcnxk_header_t *hdr = NULL;\n+\tvoid *data = NULL;\n+\tuint16_t len = 0;\n+\n+\t/* Read first bytes of type data */\n+\tdata = msg_buf;\n+\ttdata = (cnxk_type_data_t *)data;\n+\tif (tdata->type != CNXK_TYPE_HEADER) {\n+\t\tplt_err(\"Invalid type %d, type header expected\", tdata->type);\n+\t\tgoto fail;\n+\t}\n+\n+\t/* Get the header value */\n+\tdata = RTE_PTR_ADD(msg_buf, sizeof(cnxk_type_data_t));\n+\tlen += sizeof(cnxk_type_data_t);\n+\n+\t/* Validate the header */\n+\thdr = (cnxk_header_t *)data;\n+\tif (hdr->signature != CTRL_MSG_SIGNATURE) {\n+\t\tplt_err(\"Invalid signature %\" PRIu64 \" detected\", hdr->signature);\n+\t\tgoto fail;\n+\t}\n+\n+\t/* Update length read till point */\n+\tlen += tdata->length;\n+\n+\t*buf_trav_len = len;\n+\treturn 0;\n+fail:\n+\treturn errno;\n+}\n+\n+static cnxk_rep_msg_data_t *\n+message_data_extract(void *msg_buf, uint32_t *buf_trav_len)\n+{\n+\tcnxk_type_data_t *tdata = NULL;\n+\tcnxk_rep_msg_data_t *msg = NULL;\n+\tuint16_t len = *buf_trav_len;\n+\tvoid *data;\n+\n+\ttdata = (cnxk_type_data_t *)RTE_PTR_ADD(msg_buf, len);\n+\tif (tdata->type != CNXK_TYPE_MSG) {\n+\t\tplt_err(\"Invalid type %d, type MSG expected\", tdata->type);\n+\t\tgoto fail;\n+\t}\n+\n+\t/* Get the message type */\n+\tlen += sizeof(cnxk_type_data_t);\n+\tdata = RTE_PTR_ADD(msg_buf, len);\n+\tmsg = (cnxk_rep_msg_data_t *)data;\n+\n+\t/* Advance to actual message data */\n+\tlen += tdata->length;\n+\t*buf_trav_len = len;\n+\n+\treturn msg;\n+fail:\n+\treturn NULL;\n+}\n+\n+static void\n+process_ack_message(void *msg_buf, uint32_t *buf_trav_len, uint32_t msg_len, void *data)\n+{\n+\tcnxk_rep_msg_ack_data_t *adata = (cnxk_rep_msg_ack_data_t *)data;\n+\tuint16_t len = *buf_trav_len;\n+\tvoid *buf;\n+\n+\t/* Get the message type data viz ack data */\n+\tbuf = RTE_PTR_ADD(msg_buf, len);\n+\tadata->u.data = rte_zmalloc(\"Ack data\", msg_len, 0);\n+\tadata->size = msg_len;\n+\tif (adata->size == sizeof(uint64_t))\n+\t\trte_memcpy(&adata->u.data, buf, msg_len);\n+\telse\n+\t\trte_memcpy(adata->u.data, buf, msg_len);\n+\tplt_rep_dbg(\"Address %p val 0x%\" PRIu64 \" sval %\" PRId64 \" msg_len %d\",\n+\t\t    adata->u.data, adata->u.val, adata->u.sval, msg_len);\n+\n+\t/* Advance length to nex message */\n+\tlen += msg_len;\n+\t*buf_trav_len = len;\n+}\n+\n+static int\n+notify_rep_dev_ready(cnxk_rep_msg_ready_data_t *rdata, void *data,\n+\t\t     cnxk_rep_msg_ack_data1_t **padata)\n+{\n+\tstruct cnxk_eswitch_dev *eswitch_dev;\n+\tuint64_t rep_id_arr[RTE_MAX_ETHPORTS];\n+\tcnxk_rep_msg_ack_data1_t *adata;\n+\tuint16_t rep_id, sz, total_sz;\n+\tint rc, i, j = 0;\n+\n+\tPLT_SET_USED(data);\n+\teswitch_dev = cnxk_eswitch_pmd_priv();\n+\tif (!eswitch_dev) {\n+\t\tplt_err(\"Failed to get PF ethdev handle\");\n+\t\trc = -EINVAL;\n+\t\tgoto fail;\n+\t}\n+\n+\tmemset(rep_id_arr, 0, RTE_MAX_ETHPORTS * sizeof(uint64_t));\n+\t/* For ready state */\n+\tif ((rdata->nb_ports / 2) > eswitch_dev->repr_cnt.nb_repr_probed) {\n+\t\trc = CNXK_REP_CTRL_MSG_NACK_INV_REP_CNT;\n+\t\tgoto fail;\n+\t}\n+\n+\tfor (i = 0; i < rdata->nb_ports / 2; i++) {\n+\t\trep_id = UINT16_MAX;\n+\t\trc = cnxk_rep_state_update(eswitch_dev, rdata->data[i], &rep_id);\n+\t\tif (rc) {\n+\t\t\trc = CNXK_REP_CTRL_MSG_NACK_REP_STAT_UP_FAIL;\n+\t\t\tgoto fail;\n+\t\t}\n+\t\tif (rep_id != UINT16_MAX)\n+\t\t\trep_id_arr[j++] = rep_id;\n+\t}\n+\n+\t/* Send Rep Id array to companian app */\n+\tsz = j * sizeof(uint64_t);\n+\ttotal_sz = sizeof(cnxk_rep_msg_ack_data1_t) + sz;\n+\tadata = plt_zmalloc(total_sz, 0);\n+\trte_memcpy(adata->data, rep_id_arr, sz);\n+\tadata->size = sz;\n+\t*padata = adata;\n+\n+\tplt_rep_dbg(\"Installing NPC rules for Eswitch VF\");\n+\t/* Install RX VLAN rule for eswitch VF */\n+\tif (!eswitch_dev->eswitch_vf_rules_setup) {\n+\t\trc = cnxk_eswitch_pfvf_flow_rules_install(eswitch_dev, true);\n+\t\tif (rc) {\n+\t\t\tplt_err(\"Failed to install rxtx rules, rc %d\", rc);\n+\t\t\tgoto fail;\n+\t\t}\n+\n+\t\t/* Configure TPID for Eswitch PF LFs */\n+\t\trc = roc_eswitch_nix_vlan_tpid_set(&eswitch_dev->nix, ROC_NIX_VLAN_TYPE_OUTER,\n+\t\t\t\t\t\t   CNXK_ESWITCH_VLAN_TPID, true);\n+\t\tif (rc) {\n+\t\t\tplt_err(\"Failed to configure tpid, rc %d\", rc);\n+\t\t\tgoto fail;\n+\t\t}\n+\t\teswitch_dev->eswitch_vf_rules_setup = true;\n+\t}\n+\n+\treturn 0;\n+fail:\n+\tsz = sizeof(cnxk_rep_msg_ack_data1_t) + sizeof(uint64_t);\n+\tadata = plt_zmalloc(sz, 0);\n+\tadata->data[0] = rc;\n+\tadata->size = sizeof(uint64_t);\n+\t*padata = adata;\n+\n+\treturn rc;\n+}\n+\n+static int\n+process_ready_message(void *msg_buf, uint32_t *buf_trav_len, uint32_t msg_len, void *data,\n+\t\t      cnxk_rep_msg_ack_data1_t **padata)\n+{\n+\tcnxk_rep_msg_ready_data_t *rdata = NULL;\n+\tcnxk_rep_msg_ack_data1_t *adata;\n+\tuint16_t len = *buf_trav_len;\n+\tvoid *buf;\n+\tint rc = 0, sz;\n+\n+\t/* Get the message type data viz ready data */\n+\tbuf = RTE_PTR_ADD(msg_buf, len);\n+\trdata = (cnxk_rep_msg_ready_data_t *)buf;\n+\n+\tplt_rep_dbg(\"Ready data received %d, nb_ports %d\", rdata->val, rdata->nb_ports);\n+\n+\t/* Wait required to ensure other side ready for receiving the ack */\n+\tusleep(CTRL_MSG_READY_WAIT_US);\n+\n+\t/* Update all representor about ready message */\n+\tif (rdata->val) {\n+\t\trc = notify_rep_dev_ready(rdata, data, padata);\n+\t} else {\n+\t\tsz = sizeof(cnxk_rep_msg_ack_data1_t) + sizeof(uint64_t);\n+\t\tadata = plt_zmalloc(sz, 0);\n+\t\tadata->data[0] = CNXK_REP_CTRL_MSG_NACK_INV_RDY_DATA;\n+\t\tadata->size = sizeof(uint64_t);\n+\t\t*padata = adata;\n+\t}\n+\n+\t/* Advance length to nex message */\n+\tlen += msg_len;\n+\t*buf_trav_len = len;\n+\n+\treturn rc;\n+}\n+\n+static int\n+notify_rep_dev_exit(cnxk_rep_msg_exit_data_t *edata, void *data)\n+{\n+\tstruct cnxk_eswitch_dev *eswitch_dev;\n+\tstruct cnxk_rep_dev *rep_dev = NULL;\n+\tstruct rte_eth_dev *rep_eth_dev;\n+\tint i, rc = 0;\n+\n+\tPLT_SET_USED(data);\n+\teswitch_dev = cnxk_eswitch_pmd_priv();\n+\tif (!eswitch_dev) {\n+\t\tplt_err(\"Failed to get PF ethdev handle\");\n+\t\trc = -EINVAL;\n+\t\tgoto fail;\n+\t}\n+\tif ((edata->nb_ports / 2) > eswitch_dev->repr_cnt.nb_repr_probed) {\n+\t\trc = CNXK_REP_CTRL_MSG_NACK_INV_REP_CNT;\n+\t\tgoto fail;\n+\t}\n+\n+\tfor (i = 0; i < eswitch_dev->repr_cnt.nb_repr_probed; i++) {\n+\t\trep_eth_dev = eswitch_dev->rep_info[i].rep_eth_dev;\n+\t\tif (!rep_eth_dev) {\n+\t\t\tplt_err(\"Failed to get rep ethdev handle\");\n+\t\t\trc = -EINVAL;\n+\t\t\tgoto fail;\n+\t\t}\n+\n+\t\trep_dev = cnxk_rep_pmd_priv(rep_eth_dev);\n+\t\tif (!rep_dev->native_repte)\n+\t\t\trep_dev->is_vf_active = false;\n+\t}\n+\t/* For Exit message */\n+\teswitch_dev->client_connected = false;\n+\treturn 0;\n+fail:\n+\treturn rc;\n+}\n+\n+static void\n+process_exit_message(void *msg_buf, uint32_t *buf_trav_len, uint32_t msg_len, void *data)\n+{\n+\tcnxk_rep_msg_exit_data_t *edata = NULL;\n+\tuint16_t len = *buf_trav_len;\n+\tvoid *buf;\n+\n+\t/* Get the message type data viz exit data */\n+\tbuf = RTE_PTR_ADD(msg_buf, len);\n+\tedata = (cnxk_rep_msg_exit_data_t *)buf;\n+\n+\tplt_rep_dbg(\"Exit data received %d\", edata->val);\n+\n+\t/* Update all representor about ready/exit message */\n+\tif (edata->val)\n+\t\tnotify_rep_dev_exit(edata, data);\n+\n+\t/* Advance length to nex message */\n+\tlen += msg_len;\n+\t*buf_trav_len = len;\n+}\n+\n+static void\n+populate_ack_msg(void *buffer, uint32_t *length, cnxk_rep_msg_ack_data1_t *adata)\n+{\n+\tuint32_t sz = sizeof(cnxk_rep_msg_ack_data1_t) + adata->size;\n+\tuint32_t len;\n+\n+\tcnxk_rep_msg_populate_command(buffer, length, CNXK_REP_MSG_ACK, sz);\n+\n+\tlen = *length;\n+\n+\t/* Populate ACK message data */\n+\trte_memcpy(RTE_PTR_ADD(buffer, len), adata, sz);\n+\n+\tlen += sz;\n+\n+\t*length = len;\n+}\n+\n+static int\n+send_ack_message(void *data, cnxk_rep_msg_ack_data1_t *adata)\n+{\n+\tstruct cnxk_eswitch_dev *eswitch_dev = (struct cnxk_eswitch_dev *)data;\n+\tuint32_t len = 0, size;\n+\tvoid *buffer;\n+\tint rc = 0;\n+\n+\t/* Allocate memory for preparing a message */\n+\tsize = CTRL_MSG_BUFFER_SZ;\n+\tbuffer = rte_zmalloc(\"ACK msg\", size, 0);\n+\tif (!buffer) {\n+\t\tplt_err(\"Failed to allocate mem\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\t/* Prepare the ACK message */\n+\tcnxk_rep_msg_populate_header(buffer, &len);\n+\tpopulate_ack_msg(buffer, &len, adata);\n+\tcnxk_rep_msg_populate_msg_end(buffer, &len);\n+\n+\t/* Length check to avoid buffer overflow */\n+\tif (len > CTRL_MSG_BUFFER_SZ) {\n+\t\tplt_err(\"Invalid length %d for max sized buffer %d\", len, CTRL_MSG_BUFFER_SZ);\n+\t\trc = -EFAULT;\n+\t\tgoto done;\n+\t}\n+\n+\t/* Send it to the peer */\n+\trc = send_control_message(eswitch_dev, buffer, len);\n+\tif (rc)\n+\t\tplt_err(\"Failed send ack\");\n+\n+done:\n+\treturn rc;\n+}\n+\n+static int\n+process_message(void *msg_buf, uint32_t *buf_trav_len, void *data)\n+{\n+\tcnxk_rep_msg_data_t *msg = NULL;\n+\tcnxk_rep_msg_ack_data1_t *adata = NULL;\n+\tbool send_ack;\n+\tint rc = 0, sz;\n+\n+\t/* Get the message data */\n+\tmsg = message_data_extract(msg_buf, buf_trav_len);\n+\tif (!msg) {\n+\t\tplt_err(\"Failed to get message data\");\n+\t\trc = -EINVAL;\n+\t\tgoto fail;\n+\t}\n+\n+\t/* Different message type processing */\n+\twhile (msg->type != CNXK_REP_MSG_END) {\n+\t\tsend_ack = true;\n+\t\tswitch (msg->type) {\n+\t\tcase CNXK_REP_MSG_ACK:\n+\t\t\tplt_rep_dbg(\"Received ack response\");\n+\t\t\tprocess_ack_message(msg_buf, buf_trav_len, msg->length, data);\n+\t\t\tsend_ack = false;\n+\t\t\tbreak;\n+\t\tcase CNXK_REP_MSG_READY:\n+\t\t\tplt_rep_dbg(\"Received ready message\");\n+\t\t\tprocess_ready_message(msg_buf, buf_trav_len, msg->length, data, &adata);\n+\t\t\tadata->type = CNXK_REP_MSG_READY;\n+\t\t\tbreak;\n+\t\tcase CNXK_REP_MSG_EXIT:\n+\t\t\tplt_rep_dbg(\"Received exit message\");\n+\t\t\tprocess_exit_message(msg_buf, buf_trav_len, msg->length, data);\n+\t\t\tsz = sizeof(cnxk_rep_msg_ack_data1_t) + sizeof(uint64_t);\n+\t\t\tadata = plt_zmalloc(sz, 0);\n+\t\t\tadata->type = CNXK_REP_MSG_EXIT;\n+\t\t\tadata->data[0] = 0;\n+\t\t\tadata->size = sizeof(uint64_t);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tsend_ack = false;\n+\t\t\tplt_err(\"Invalid message type: %d\", msg->type);\n+\t\t\trc = -EINVAL;\n+\t\t};\n+\n+\t\t/* Send ACK */\n+\t\tif (send_ack)\n+\t\t\tsend_ack_message(data, adata);\n+\n+\t\t/* Advance to next message */\n+\t\tmsg = message_data_extract(msg_buf, buf_trav_len);\n+\t\tif (!msg) {\n+\t\t\tplt_err(\"Failed to get message data\");\n+\t\t\trc = -EINVAL;\n+\t\t\tgoto fail;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+fail:\n+\treturn rc;\n+}\n+\n+static int\n+process_control_message(void *msg_buf, void *data, size_t sz)\n+{\n+\tuint32_t buf_trav_len = 0;\n+\tint rc;\n+\n+\t/* Validate the validity of the received message */\n+\tparse_validate_header(msg_buf, &buf_trav_len);\n+\n+\t/* Detect message and process */\n+\trc = process_message(msg_buf, &buf_trav_len, data);\n+\tif (rc) {\n+\t\tplt_err(\"Failed to process message\");\n+\t\tgoto fail;\n+\t}\n+\n+\t/* Ensuring entire message has been processed */\n+\tif (sz != buf_trav_len) {\n+\t\tplt_err(\"Out of %\" PRId64 \" bytes %d bytes of msg_buf processed\", sz, buf_trav_len);\n+\t\trc = -EFAULT;\n+\t\tgoto fail;\n+\t}\n+\n+\treturn 0;\n+fail:\n+\treturn rc;\n+}\n+\n+static int\n+receive_control_msg_resp(struct cnxk_eswitch_dev *eswitch_dev, void *data)\n+{\n+\tuint32_t wait_us = CTRL_MSG_RCV_TIMEOUT_MS * 1000;\n+\tuint32_t timeout = 0, sleep = 1;\n+\tint sz = 0;\n+\tint rc = -1;\n+\tuint32_t len = BUFSIZ;\n+\tvoid *msg_buf;\n+\n+\tmsg_buf = plt_zmalloc(len, 0);\n+\n+\tdo {\n+\t\tsz = receive_control_message(eswitch_dev->sock_fd, msg_buf, len);\n+\t\tif (sz != 0)\n+\t\t\tbreak;\n+\n+\t\t/* Timeout after CTRL_MSG_RCV_TIMEOUT_MS */\n+\t\tif (timeout >= wait_us) {\n+\t\t\tplt_err(\"Control message wait timedout\");\n+\t\t\treturn -ETIMEDOUT;\n+\t\t}\n+\n+\t\tplt_delay_us(sleep);\n+\t\ttimeout += sleep;\n+\t} while ((sz == 0) || (timeout < wait_us));\n+\n+\tif (sz > 0) {\n+\t\tplt_rep_dbg(\"Received %d sized response packet\", sz);\n+\t\trc = process_control_message(msg_buf, data, sz);\n+\t\tplt_free(msg_buf);\n+\t}\n+\n+\treturn rc;\n+}\n+\n+int\n+cnxk_rep_msg_send_process(struct cnxk_rep_dev *rep_dev, void *buffer, uint32_t len,\n+\t\t\t  cnxk_rep_msg_ack_data_t *adata)\n+{\n+\tstruct cnxk_eswitch_dev *eswitch_dev;\n+\tint rc = 0;\n+\n+\teswitch_dev = rep_dev->parent_dev;\n+\tif (!eswitch_dev) {\n+\t\tplt_err(\"Failed to get parent eswitch handle\");\n+\t\trc = -1;\n+\t\tgoto fail;\n+\t}\n+\n+\tplt_spinlock_lock(&eswitch_dev->rep_lock);\n+\trc = send_control_message(eswitch_dev, buffer, len);\n+\tif (rc) {\n+\t\tplt_err(\"Failed to send the message, err %d\", rc);\n+\t\tgoto free;\n+\t}\n+\n+\t/* Get response of the command sent */\n+\trc = receive_control_msg_resp(eswitch_dev, adata);\n+\tif (rc) {\n+\t\tplt_err(\"Failed to receive the response, err %d\", rc);\n+\t\tgoto free;\n+\t}\n+\tplt_spinlock_unlock(&eswitch_dev->rep_lock);\n+\n+\treturn 0;\n+free:\n+\tplt_spinlock_unlock(&eswitch_dev->rep_lock);\n+fail:\n+\treturn rc;\n+}\n+\n+static void\n+poll_for_control_msg(void *data)\n+{\n+\tstruct cnxk_eswitch_dev *eswitch_dev = (struct cnxk_eswitch_dev *)data;\n+\tuint32_t len = BUFSIZ;\n+\tint sz = 0;\n+\tvoid *msg_buf;\n+\n+\twhile (eswitch_dev->client_connected) {\n+\t\tmsg_buf = plt_zmalloc(len, 0);\n+\t\tdo {\n+\t\t\tplt_spinlock_lock(&eswitch_dev->rep_lock);\n+\t\t\tsz = receive_control_message(eswitch_dev->sock_fd, msg_buf, len);\n+\t\t\tplt_spinlock_unlock(&eswitch_dev->rep_lock);\n+\t\t\tif (sz != 0)\n+\t\t\t\tbreak;\n+\t\t\tplt_delay_us(2000);\n+\t\t} while (sz == 0);\n+\n+\t\tif (sz > 0) {\n+\t\t\tplt_rep_dbg(\"Received new %d bytes control message\", sz);\n+\t\t\tplt_spinlock_lock(&eswitch_dev->rep_lock);\n+\t\t\tprocess_control_message(msg_buf, data, sz);\n+\t\t\tplt_spinlock_unlock(&eswitch_dev->rep_lock);\n+\t\t\tplt_free(msg_buf);\n+\t\t}\n+\t}\n+\tplt_rep_dbg(\"Exiting poll for control message loop\");\n+}\n+\n+static uint32_t\n+rep_ctrl_msg_thread_main(void *arg)\n+{\n+\tstruct cnxk_eswitch_dev *eswitch_dev = (struct cnxk_eswitch_dev *)arg;\n+\tstruct sockaddr_un client;\n+\tint addr_len;\n+\tint ssock_fd;\n+\tint sock_fd;\n+\n+\tssock_fd = open_socket_ctrl_channel();\n+\tif (ssock_fd < 0) {\n+\t\tplt_err(\"Failed to open socket for ctrl channel, err %d\", ssock_fd);\n+\t\treturn UINT32_MAX;\n+\t}\n+\n+\taddr_len = sizeof(client);\n+\twhile (eswitch_dev->start_ctrl_msg_thrd) {\n+\t\t/* Accept client connection until the thread is running */\n+\t\tsock_fd = accept(ssock_fd, (struct sockaddr *)&client, (socklen_t *)&addr_len);\n+\t\tif (sock_fd < 0) {\n+\t\t\tplt_err(\"Failed to accept connection request on socket fd %d\", ssock_fd);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tplt_rep_dbg(\"Client %s: Connection request accepted.\", client.sun_path);\n+\t\teswitch_dev->sock_fd = sock_fd;\n+\t\tif (eswitch_dev->start_ctrl_msg_thrd) {\n+\t\t\teswitch_dev->client_connected = true;\n+\t\t\tpoll_for_control_msg(eswitch_dev);\n+\t\t}\n+\t\teswitch_dev->sock_fd = -1;\n+\t\tclose(sock_fd);\n+\t}\n+\n+\t/* Closing the opened socket */\n+\tclose_socket(ssock_fd);\n+\tplt_rep_dbg(\"Exiting representor ctrl thread\");\n+\n+\treturn 0;\n+}\n+\n+int\n+cnxk_rep_msg_control_thread_launch(struct cnxk_eswitch_dev *eswitch_dev)\n+{\n+\tchar name[CTRL_MSG_THRD_NAME_LEN];\n+\tint rc = 0;\n+\n+\trte_strscpy(name, \"rep_ctrl_msg_hndlr\", CTRL_MSG_THRD_NAME_LEN);\n+\teswitch_dev->start_ctrl_msg_thrd = true;\n+\trc = rte_thread_create_internal_control(&eswitch_dev->rep_ctrl_msg_thread, name,\n+\t\t\t\t\t\trep_ctrl_msg_thread_main, eswitch_dev);\n+\tif (rc)\n+\t\tplt_err(\"Failed to create rep control message handling\");\n+\n+\treturn rc;\n+}\ndiff --git a/drivers/net/cnxk/cnxk_rep_msg.h b/drivers/net/cnxk/cnxk_rep_msg.h\nnew file mode 100644\nindex 0000000000..0543805148\n--- /dev/null\n+++ b/drivers/net/cnxk/cnxk_rep_msg.h\n@@ -0,0 +1,95 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2024 Marvell.\n+ */\n+\n+#ifndef __CNXK_REP_MSG_H__\n+#define __CNXK_REP_MSG_H__\n+\n+#include <stdint.h>\n+\n+#define CNXK_REP_MSG_MAX_BUFFER_SZ 1500\n+\n+typedef enum CNXK_TYPE {\n+\tCNXK_TYPE_HEADER = 0,\n+\tCNXK_TYPE_MSG,\n+} cnxk_type_t;\n+\n+typedef enum CNXK_REP_MSG {\n+\t/* General sync messages */\n+\tCNXK_REP_MSG_READY = 0,\n+\tCNXK_REP_MSG_ACK,\n+\tCNXK_REP_MSG_EXIT,\n+\t/* End of messaging sequence */\n+\tCNXK_REP_MSG_END,\n+} cnxk_rep_msg_t;\n+\n+typedef enum CNXK_NACK_CODE {\n+\tCNXK_REP_CTRL_MSG_NACK_INV_RDY_DATA = 0x501,\n+\tCNXK_REP_CTRL_MSG_NACK_INV_REP_CNT = 0x502,\n+\tCNXK_REP_CTRL_MSG_NACK_REP_STAT_UP_FAIL = 0x503,\n+} cnxk_nack_code_t;\n+\n+/* Types */\n+typedef struct cnxk_type_data {\n+\tcnxk_type_t type;\n+\tuint32_t length;\n+\tuint64_t data[];\n+} __rte_packed cnxk_type_data_t;\n+\n+/* Header */\n+typedef struct cnxk_header {\n+\tuint64_t signature;\n+\tuint16_t nb_hops;\n+} __rte_packed cnxk_header_t;\n+\n+/* Message meta */\n+typedef struct cnxk_rep_msg_data {\n+\tcnxk_rep_msg_t type;\n+\tuint32_t length;\n+\tuint64_t data[];\n+} __rte_packed cnxk_rep_msg_data_t;\n+\n+/* Ack msg */\n+typedef struct cnxk_rep_msg_ack_data {\n+\tcnxk_rep_msg_t type;\n+\tuint32_t size;\n+\tunion {\n+\t\tvoid *data;\n+\t\tuint64_t val;\n+\t\tint64_t sval;\n+\t} u;\n+} __rte_packed cnxk_rep_msg_ack_data_t;\n+\n+/* Ack msg */\n+typedef struct cnxk_rep_msg_ack_data1 {\n+\tcnxk_rep_msg_t type;\n+\tuint32_t size;\n+\tuint64_t data[];\n+} __rte_packed cnxk_rep_msg_ack_data1_t;\n+\n+/* Ready msg */\n+typedef struct cnxk_rep_msg_ready_data {\n+\tuint8_t val;\n+\tuint16_t nb_ports;\n+\tuint16_t data[];\n+} __rte_packed cnxk_rep_msg_ready_data_t;\n+\n+/* Exit msg */\n+typedef struct cnxk_rep_msg_exit_data {\n+\tuint8_t val;\n+\tuint16_t nb_ports;\n+\tuint16_t data[];\n+} __rte_packed cnxk_rep_msg_exit_data_t;\n+\n+void cnxk_rep_msg_populate_command(void *buffer, uint32_t *length, cnxk_rep_msg_t type,\n+\t\t\t\t   uint32_t size);\n+void cnxk_rep_msg_populate_command_meta(void *buffer, uint32_t *length, void *msg_meta, uint32_t sz,\n+\t\t\t\t\tcnxk_rep_msg_t msg);\n+void cnxk_rep_msg_populate_msg_end(void *buffer, uint32_t *length);\n+void cnxk_rep_msg_populate_type(void *buffer, uint32_t *length, cnxk_type_t type, uint32_t sz);\n+void cnxk_rep_msg_populate_header(void *buffer, uint32_t *length);\n+int cnxk_rep_msg_send_process(struct cnxk_rep_dev *rep_dev, void *buffer, uint32_t len,\n+\t\t\t      cnxk_rep_msg_ack_data_t *adata);\n+int cnxk_rep_msg_control_thread_launch(struct cnxk_eswitch_dev *eswitch_dev);\n+\n+#endif /* __CNXK_REP_MSG_H__ */\ndiff --git a/drivers/net/cnxk/meson.build b/drivers/net/cnxk/meson.build\nindex 7121845dc6..9ca7732713 100644\n--- a/drivers/net/cnxk/meson.build\n+++ b/drivers/net/cnxk/meson.build\n@@ -37,6 +37,7 @@ sources = files(\n         'cnxk_ptp.c',\n         'cnxk_flow.c',\n         'cnxk_rep.c',\n+        'cnxk_rep_msg.c',\n         'cnxk_rep_ops.c',\n         'cnxk_stats.c',\n         'cnxk_tm.c',\n",
    "prefixes": [
        "v3",
        "10/23"
    ]
}