requester: Add af_mctp transport
Change-Id: I97641973fb85070876c11003a9758faa707f4a46
Signed-off-by: Rashmica Gupta <rashmica@linux.ibm.com>
diff --git a/include/libpldm/meson.build b/include/libpldm/meson.build
index 39c53ea..fce591f 100644
--- a/include/libpldm/meson.build
+++ b/include/libpldm/meson.build
@@ -34,6 +34,7 @@
)
libpldm_transport_headers += files(
'transport.h',
+ 'transport/af-mctp.h',
'transport/mctp-demux.h'
)
endif
diff --git a/include/libpldm/transport/af-mctp.h b/include/libpldm/transport/af-mctp.h
new file mode 100644
index 0000000..2b788f7
--- /dev/null
+++ b/include/libpldm/transport/af-mctp.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
+#ifndef LIBPLDM_AF_MCTP_H
+#define LIBPLDM_AF_MCTP_H
+#include "../config.h"
+#include "libpldm/base.h"
+#include "libpldm/pldm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct pldm_transport_af_mctp;
+
+/* Init the transport backend */
+int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx);
+
+/* Destroy the transport backend */
+void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx);
+
+/* Get the core pldm transport struct */
+struct pldm_transport *
+pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx);
+
+#ifdef PLDM_HAS_POLL
+struct pollfd;
+/* Init pollfd for async calls */
+int pldm_transport_af_mctp_init_pollfd(struct pldm_transport_af_mctp *ctx,
+ struct pollfd *pollfd);
+#endif
+
+/* Inserts a TID-to-EID mapping into the transport's device map */
+int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
+ pldm_tid_t tid, mctp_eid_t eid);
+
+/* Removes a TID-to-EID mapping from the transport's device map */
+int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
+ pldm_tid_t tid, mctp_eid_t eid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBPLDM_AF MCTP*/
diff --git a/src/transport/af-mctp.c b/src/transport/af-mctp.c
new file mode 100644
index 0000000..21d2c72
--- /dev/null
+++ b/src/transport/af-mctp.c
@@ -0,0 +1,157 @@
+#include "../mctp-defines.h"
+#include "base.h"
+#include "container-of.h"
+#include "libpldm/pldm.h"
+#include "libpldm/transport.h"
+#include "transport.h"
+
+#include <errno.h>
+#include <linux/mctp.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#define AF_MCTP_NAME "AF_MCTP"
+struct pldm_transport_af_mctp {
+ struct pldm_transport transport;
+ int socket;
+ pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
+};
+
+#define transport_to_af_mctp(ptr) \
+ container_of(ptr, struct pldm_transport_af_mctp, transport)
+
+struct pldm_transport *
+pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
+{
+ return &ctx->transport;
+}
+
+int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
+ struct pollfd *pollfd)
+{
+ struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
+ pollfd->fd = ctx->socket;
+ pollfd->events = POLLIN;
+ return 0;
+}
+
+static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
+ pldm_tid_t tid, mctp_eid_t *eid)
+{
+ int i;
+ for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
+ if (ctx->tid_eid_map[i] == tid) {
+ *eid = i;
+ return 0;
+ }
+ }
+ *eid = -1;
+ return -1;
+}
+
+int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
+ pldm_tid_t tid, mctp_eid_t eid)
+{
+ ctx->tid_eid_map[eid] = tid;
+
+ return 0;
+}
+
+int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
+ __attribute__((unused)) pldm_tid_t tid,
+ mctp_eid_t eid)
+{
+ ctx->tid_eid_map[eid] = 0;
+
+ return 0;
+}
+
+static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
+ pldm_tid_t tid,
+ void **pldm_resp_msg,
+ size_t *resp_msg_len)
+{
+ struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
+ mctp_eid_t eid = 0;
+ int rc = pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid);
+ if (rc) {
+ return PLDM_REQUESTER_RECV_FAIL;
+ }
+
+ ssize_t length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
+ if (length <= 0) {
+ return PLDM_REQUESTER_RECV_FAIL;
+ }
+ *pldm_resp_msg = malloc(length);
+ length = recv(af_mctp->socket, *pldm_resp_msg, length, MSG_TRUNC);
+ if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
+ free(*pldm_resp_msg);
+ return PLDM_REQUESTER_INVALID_RECV_LEN;
+ }
+ *resp_msg_len = length;
+ return PLDM_REQUESTER_SUCCESS;
+}
+
+static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
+ pldm_tid_t tid,
+ const void *pldm_req_msg,
+ size_t req_msg_len)
+{
+ struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
+ mctp_eid_t eid = 0;
+ if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
+ return PLDM_REQUESTER_SEND_FAIL;
+ }
+
+ struct sockaddr_mctp addr = {0};
+ addr.smctp_family = AF_MCTP;
+ addr.smctp_addr.s_addr = eid;
+ addr.smctp_type = MCTP_MSG_TYPE_PLDM;
+ addr.smctp_tag = MCTP_TAG_OWNER;
+
+ ssize_t rc = sendto(af_mctp->socket, pldm_req_msg, req_msg_len, 0,
+ (struct sockaddr *)&addr, sizeof(addr));
+ if (rc == -1) {
+ return PLDM_REQUESTER_SEND_FAIL;
+ }
+ return PLDM_REQUESTER_SUCCESS;
+}
+
+int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
+{
+ if (!ctx || *ctx) {
+ return -EINVAL;
+ }
+
+ struct pldm_transport_af_mctp *af_mctp =
+ calloc(1, sizeof(struct pldm_transport_af_mctp));
+ if (!af_mctp) {
+ return -ENOMEM;
+ }
+
+ af_mctp->transport.name = AF_MCTP_NAME;
+ af_mctp->transport.version = 1;
+ af_mctp->transport.recv = pldm_transport_af_mctp_recv;
+ af_mctp->transport.send = pldm_transport_af_mctp_send;
+ af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
+ if (af_mctp->socket == -1) {
+ free(af_mctp);
+ return -1;
+ }
+ *ctx = af_mctp;
+ return 0;
+}
+
+void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ close(ctx->socket);
+ free(ctx);
+}
diff --git a/src/transport/meson.build b/src/transport/meson.build
index 1a2acc9..1fcc06a 100644
--- a/src/transport/meson.build
+++ b/src/transport/meson.build
@@ -1,4 +1,5 @@
libpldm_sources += files(
+ 'af-mctp.c',
'mctp-demux.c',
'transport.c'
)