blob: 2b33ef57a9d3daecfb0962e3007e0a9066de3835 [file]
From e2069d7ee735aef12defc6a749d5d9a58cc7ff12 Mon Sep 17 00:00:00 2001
From: Harsh Tyagi <harshtya@google.com>
Date: Mon, 24 Jul 2023 22:21:46 +0000
Subject: [PATCH] Add support for network id in pldm_send and pldm_recv
Tested:
Tested on a dev board that supported MCTP over PLDM communication by
connecting multiple PLDM devices and send/recv on diff network id but same eid
Patch Tracking Bug: 282042978
Upstream-Status: Inappropriate
Upstream info / review: https://gerrit.openbmc.org/c/openbmc/libpldm/+/64422
Justification: This change will be supported under AF_MCTP topic upstream
https://gerrit.openbmc.org/q/topic:AF_MCTP (If not the above code will be
reviewed)
---
include/libpldm/pldm.h | 36 ++++++++++++
src/requester/pldm.c | 121 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 157 insertions(+)
diff --git a/include/libpldm/pldm.h b/include/libpldm/pldm.h
index d36c4c9..5a4d5d6 100644
--- a/include/libpldm/pldm.h
+++ b/include/libpldm/pldm.h
@@ -113,6 +113,42 @@ pldm_requester_rc_t pldm_recv_any(mctp_eid_t eid, int mctp_fd,
uint8_t **pldm_resp_msg,
size_t *resp_msg_len);
+/**
+ * @brief Similar to pldm send but sends the PLDM request to a specific network id
+ *
+ * @param[in] eid - destination MCTP eid
+ * @param[in] network_id - Net id to send the request to
+ * @param[in] mctp_fd - MCTP socket fd
+ * @param[in] pldm_req_msg - caller owned pointer to PLDM request msg
+ * @param[in] req_msg_len - size of PLDM request msg
+*/
+pldm_requester_rc_t pldm_send_at_network(mctp_eid_t eid, int network_id,
+ int mctp_fd,
+ const uint8_t* pldm_req_msg,
+ size_t req_msg_len);
+
+/**
+ * @brief Similar to pldm_recv but receives from a specific network id
+ *
+ * @param[in] eid - destination MCTP eid
+ * @param[in] mctp_fd - MCTP socket fd
+ * @param[in] instance_id - PLDM instance id of previously sent PLDM request msg
+ * @param[out] pldm_resp_msg - *pldm_resp_msg will point to PLDM response msg,
+ * this function allocates memory, caller to free(*pldm_resp_msg) on
+ * success.
+ * @param[out] resp_msg_len - caller owned pointer that will be made point to
+ * the size of the PLDM response msg.
+ *
+ * @param[in] network_id - Net id to receive the request from
+ *
+ * @return pldm_requester_rc_t (errno may be set). failure is returned even
+ * when data was read, but didn't match eid or instance_id.
+*/
+pldm_requester_rc_t pldm_recv_at_network(mctp_eid_t eid, int mctp_fd,
+ uint8_t instance_id,
+ uint8_t** pldm_resp_msg,
+ size_t* resp_msg_len, int network_id);
+
/**
* @brief Shutdown the MCTP socket
*/
diff --git a/src/requester/pldm.c b/src/requester/pldm.c
index b83fd96..4bbb13c 100644
--- a/src/requester/pldm.c
+++ b/src/requester/pldm.c
@@ -12,6 +12,8 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
+#include <stdio.h>
+#include "mctp-defines.h"
/* Temporary for old api */
#include <libpldm/transport/mctp-demux.h>
@@ -221,3 +223,122 @@ void pldm_close(void)
}
open_transport = NULL;
}
+
+LIBPLDM_ABI_STABLE
+pldm_requester_rc_t pldm_send_at_network(mctp_eid_t eid, int network_id,
+ int mctp_fd,
+ const uint8_t* pldm_req_msg,
+ size_t req_msg_len)
+{
+ struct sockaddr_mctp addr = {0};
+ addr.smctp_family = AF_MCTP;
+ addr.smctp_network = network_id;
+ addr.smctp_addr.s_addr = eid;
+ addr.smctp_type = MCTP_MSG_TYPE_PLDM;
+ addr.smctp_tag = MCTP_TAG_OWNER;
+
+ int rc = sendto(mctp_fd, (uint8_t*)pldm_req_msg, req_msg_len, 0,
+ (struct sockaddr*)&addr, sizeof(addr));
+
+ if (rc == -1)
+ {
+ perror("FAILED ON SEND LIBPLDM");
+ return PLDM_REQUESTER_SEND_FAIL;
+ }
+ return PLDM_REQUESTER_SUCCESS;
+}
+
+static pldm_requester_rc_t mctp_recv_at_network(mctp_eid_t eid, int mctp_fd,
+ uint8_t** pldm_resp_msg,
+ size_t* resp_msg_len,
+ int network_id)
+{
+ ssize_t min_len = sizeof(struct pldm_msg_hdr);
+ 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;
+ addr.smctp_network = network_id;
+ socklen_t addrlen = sizeof(addr);
+ ssize_t length = recvfrom(mctp_fd, NULL, 0, MSG_PEEK | MSG_TRUNC,
+ (struct sockaddr*)&addr, &addrlen);
+ if (length <= 0)
+ {
+ return PLDM_REQUESTER_RECV_FAIL;
+ }
+ else if (length < min_len)
+ {
+ /* read and discard */
+ uint8_t buf[length];
+ recv(mctp_fd, buf, length, 0);
+ return PLDM_REQUESTER_INVALID_RECV_LEN;
+ }
+ else
+ {
+ ssize_t bytes = recvfrom(mctp_fd, *pldm_resp_msg, length, MSG_TRUNC,
+ (struct sockaddr*)&addr, &addrlen);
+ if (length != bytes)
+ {
+ free(*pldm_resp_msg);
+ return PLDM_REQUESTER_INVALID_RECV_LEN;
+ }
+ *resp_msg_len = length;
+ return PLDM_REQUESTER_SUCCESS;
+ }
+}
+
+pldm_requester_rc_t recv_at_network(mctp_eid_t eid, int mctp_fd,
+ uint8_t** pldm_resp_msg,
+ size_t* resp_msg_len, int network_id)
+{
+ pldm_requester_rc_t rc = mctp_recv_at_network(eid, mctp_fd, pldm_resp_msg,
+ resp_msg_len, network_id);
+ if (rc != PLDM_REQUESTER_SUCCESS)
+ {
+ fprintf(stderr,
+ "MCTP Data Failure: No data received on eid:%u, nid:%d\n",
+ eid, network_id);
+ return rc;
+ }
+
+ struct pldm_msg_hdr* hdr = (struct pldm_msg_hdr*)(*pldm_resp_msg);
+ if (hdr->request != PLDM_RESPONSE)
+ {
+ free(*pldm_resp_msg);
+ return PLDM_REQUESTER_NOT_RESP_MSG;
+ }
+
+ uint8_t pldm_rc = 0;
+ if (*resp_msg_len < (sizeof(struct pldm_msg_hdr) + sizeof(pldm_rc)))
+ {
+ free(*pldm_resp_msg);
+ return PLDM_REQUESTER_RESP_MSG_TOO_SMALL;
+ }
+
+ return PLDM_REQUESTER_SUCCESS;
+}
+
+LIBPLDM_ABI_STABLE
+pldm_requester_rc_t pldm_recv_at_network(mctp_eid_t eid, int mctp_fd,
+ uint8_t instance_id,
+ uint8_t** pldm_resp_msg,
+ size_t* resp_msg_len, int network_id)
+{
+ pldm_requester_rc_t rc = recv_at_network(eid, mctp_fd, pldm_resp_msg,
+ resp_msg_len, network_id);
+
+ if (rc != PLDM_REQUESTER_SUCCESS)
+ {
+ return rc;
+ }
+
+ struct pldm_msg_hdr* hdr = (struct pldm_msg_hdr*)(*pldm_resp_msg);
+ if (hdr->instance_id != instance_id)
+ {
+ free(*pldm_resp_msg);
+ return PLDM_REQUESTER_INSTANCE_ID_MISMATCH;
+ }
+
+ return PLDM_REQUESTER_SUCCESS;
+}
--
2.43.0.rc2.451.g8631bc7472-goog