| 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 |
| |