Add kernel MCTP (AF_MCTP) support and transport-implementation option

-Added support for kernel MCTP (AF_MCTP) to enable MCTP communication
 using AF_MCTP sockets.
- Introduced a new configuration option 'transport-implementation'

The 'transport-implementation' option can be set to either:
- 'mctp-demux': Uses the existing mctp-demux transport method.
- 'af-mctp': Uses the new kernel AF_MCTP transport method.

Change-Id: Ib2f7b97d0a96ceaa0cb0fc8cd7313e84c03bbd61
Signed-off-by: Pavithra Barithaya <pavithrabarithaya07@gmail.com>
diff --git a/meson.build b/meson.build
index a0fa425..7fea7c2 100644
--- a/meson.build
+++ b/meson.build
@@ -45,6 +45,12 @@
 
 conf.set('CONFIG_PHAL_API', get_option('phal').allowed())
 
+if(get_option('transport-implementation')) == 'mctp-demux'
+   add_project_arguments('-DPLDM_TRANSPORT_WITH_MCTP_DEMUX', language : 'cpp')
+else
+   add_project_arguments('-DPLDM_TRANSPORT_WITH_AF_MCTP', language: 'cpp')
+endif
+
 if cmplr.has_header('poll.h')
     add_project_arguments('-DPLDM_HAS_POLL=1', language: 'cpp')
 endif
diff --git a/meson.options b/meson.options
index 968d31a..4c08be3 100644
--- a/meson.options
+++ b/meson.options
@@ -19,3 +19,9 @@
     value: '/org/openpower/dump',
     description: 'Object path requesting OpenPOWER dumps',
 )
+option(
+    'transport-implementation',
+    type: 'combo',
+    choices: ['mctp-demux', 'af-mctp'],
+    description: 'transport via af-mctp or mctp-demux',
+)
diff --git a/util/pldm.cpp b/util/pldm.cpp
index daa28c4..b0ab387 100644
--- a/util/pldm.cpp
+++ b/util/pldm.cpp
@@ -4,6 +4,7 @@
 #include <libpldm/platform.h>
 #include <libpldm/pldm.h>
 #include <libpldm/transport.h>
+#include <libpldm/transport/af-mctp.h>
 #include <libpldm/transport/mctp-demux.h>
 #include <poll.h>
 
@@ -50,6 +51,18 @@
     /** @brief sending PLDM file */
     bool sendPldm(const std::vector<uint8_t>& request, uint8_t mctpEid);
 
+    /** @brief Opens the MCTP AF_MCTP for sending and receiving messages.
+     *
+     * @param[in] eid - MCTP endpoint ID
+     */
+    int openAfMctpTransport(mctp_eid_t eid);
+
+    union TransportImpl
+    {
+        pldm_transport_mctp_demux* mctpDemux;
+        pldm_transport_af_mctp* afMctp;
+    };
+
   private:
     // Private constructor and destructor to prevent creating multiple instances
     PLDMInstanceManager();
@@ -65,7 +78,8 @@
     /** pldm transport instance  */
     struct pldm_transport* pldmTransport = NULL;
 
-    pldm_transport_mctp_demux* mctpDemux;
+    // type of transport implementation instance
+    TransportImpl impl;
 };
 
 PLDMInstanceManager::PLDMInstanceManager() : pldmInstanceIdDb(nullptr)
@@ -139,7 +153,13 @@
         trace::inf("open: pldmTransport already setup!");
         return fd;
     }
+#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
     fd = openMctpDemuxTransport(eid);
+#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
+    fd = openAfMctpTransport(eid);
+#else
+    trace::err("open: No valid transport defined!");
+#endif
     if (fd < 0)
     {
         auto e = errno;
@@ -148,9 +168,10 @@
     return fd;
 }
 
-int PLDMInstanceManager::openMctpDemuxTransport(mctp_eid_t eid)
+[[maybe_unused]] int PLDMInstanceManager::openMctpDemuxTransport(mctp_eid_t eid)
 {
-    int rc = pldm_transport_mctp_demux_init(&mctpDemux);
+    impl.mctpDemux = nullptr;
+    int rc = pldm_transport_mctp_demux_init(&impl.mctpDemux);
     if (rc)
     {
         trace::err(
@@ -160,7 +181,7 @@
         return rc;
     }
 
-    rc = pldm_transport_mctp_demux_map_tid(mctpDemux, eid, eid);
+    rc = pldm_transport_mctp_demux_map_tid(impl.mctpDemux, eid, eid);
     if (rc)
     {
         trace::err(
@@ -170,7 +191,7 @@
         return rc;
     }
 
-    pldmTransport = pldm_transport_mctp_demux_core(mctpDemux);
+    pldmTransport = pldm_transport_mctp_demux_core(impl.mctpDemux);
     struct pollfd pollfd;
     rc = pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd);
     if (rc)
@@ -182,10 +203,49 @@
     }
     return pollfd.fd;
 }
+
+[[maybe_unused]] int PLDMInstanceManager::openAfMctpTransport(mctp_eid_t eid)
+{
+    impl.afMctp = nullptr;
+    int rc = pldm_transport_af_mctp_init(&impl.afMctp);
+    if (rc)
+    {
+        trace::err(
+            "openAfMctpTransport: Failed to init AF MCTP transport. rc = %d",
+            (unsigned)rc);
+        return rc;
+    }
+    rc = pldm_transport_af_mctp_map_tid(impl.afMctp, eid, eid);
+    if (rc)
+    {
+        trace::err(
+            "openAfMctpTransport: Failed to setup tid to eid mapping. rc = %d",
+            (unsigned)rc);
+        closePLDM();
+        return rc;
+    }
+    pldmTransport = pldm_transport_af_mctp_core(impl.afMctp);
+    struct pollfd pollfd;
+    rc = pldm_transport_af_mctp_init_pollfd(pldmTransport, &pollfd);
+    if (rc)
+    {
+        trace::err("openAfMctpTransport: Failed to get pollfd. rc = %d",
+                   (unsigned)rc);
+        closePLDM();
+        return rc;
+    }
+    return pollfd.fd;
+}
+
 void PLDMInstanceManager::closePLDM()
 {
-    pldm_transport_mctp_demux_destroy(mctpDemux);
-    mctpDemux = NULL;
+#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
+    pldm_transport_mctp_demux_destroy(impl.mctpDemux);
+    impl.mctpDemux = nullptr;
+#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
+    pldm_transport_af_mctp_destroy(impl.afMctp);
+    impl.afMctp = nullptr;
+#endif
     pldmTransport = NULL;
 }