blob: 4766d1429471aa5aabb184e09d061e459527a2f4 [file] [log] [blame]
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301#include "mctp-defines.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +11002#include "base.h"
3#include "container-of.h"
4#include "libpldm/pldm.h"
5#include "libpldm/transport.h"
Rashmica Gupta04273e92023-06-16 16:03:37 +10006#include "socket.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +11007#include "transport.h"
8
9#include <errno.h>
Rashmica Gupta04273e92023-06-16 16:03:37 +100010#include <limits.h>
Rashmica Guptaba6971b2022-12-09 16:27:38 +110011#include <linux/mctp.h>
12#include <poll.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/socket.h>
16#include <sys/types.h>
17#include <sys/un.h>
18#include <unistd.h>
19
20#define AF_MCTP_NAME "AF_MCTP"
21struct pldm_transport_af_mctp {
22 struct pldm_transport transport;
23 int socket;
24 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
Rashmica Gupta04273e92023-06-16 16:03:37 +100025 struct pldm_socket_sndbuf socket_send_buf;
Rashmica Guptaba6971b2022-12-09 16:27:38 +110026};
27
28#define transport_to_af_mctp(ptr) \
29 container_of(ptr, struct pldm_transport_af_mctp, transport)
30
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093031LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +110032struct pldm_transport *
33pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
34{
35 return &ctx->transport;
36}
37
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093038LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +110039int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
40 struct pollfd *pollfd)
41{
42 struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
43 pollfd->fd = ctx->socket;
44 pollfd->events = POLLIN;
45 return 0;
46}
47
48static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
49 pldm_tid_t tid, mctp_eid_t *eid)
50{
51 int i;
52 for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
53 if (ctx->tid_eid_map[i] == tid) {
54 *eid = i;
55 return 0;
56 }
57 }
58 *eid = -1;
59 return -1;
60}
61
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093062LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +110063int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
64 pldm_tid_t tid, mctp_eid_t eid)
65{
66 ctx->tid_eid_map[eid] = tid;
67
68 return 0;
69}
70
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093071LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +110072int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
73 __attribute__((unused)) pldm_tid_t tid,
74 mctp_eid_t eid)
75{
76 ctx->tid_eid_map[eid] = 0;
77
78 return 0;
79}
80
81static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
82 pldm_tid_t tid,
83 void **pldm_resp_msg,
84 size_t *resp_msg_len)
85{
86 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
87 mctp_eid_t eid = 0;
88 int rc = pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid);
89 if (rc) {
90 return PLDM_REQUESTER_RECV_FAIL;
91 }
92
93 ssize_t length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
94 if (length <= 0) {
95 return PLDM_REQUESTER_RECV_FAIL;
96 }
97 *pldm_resp_msg = malloc(length);
98 length = recv(af_mctp->socket, *pldm_resp_msg, length, MSG_TRUNC);
99 if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
100 free(*pldm_resp_msg);
101 return PLDM_REQUESTER_INVALID_RECV_LEN;
102 }
103 *resp_msg_len = length;
104 return PLDM_REQUESTER_SUCCESS;
105}
106
107static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
108 pldm_tid_t tid,
109 const void *pldm_req_msg,
110 size_t req_msg_len)
111{
112 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
113 mctp_eid_t eid = 0;
114 if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
115 return PLDM_REQUESTER_SEND_FAIL;
116 }
117
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930118 struct sockaddr_mctp addr = { 0 };
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100119 addr.smctp_family = AF_MCTP;
120 addr.smctp_addr.s_addr = eid;
121 addr.smctp_type = MCTP_MSG_TYPE_PLDM;
122 addr.smctp_tag = MCTP_TAG_OWNER;
123
Rashmica Gupta04273e92023-06-16 16:03:37 +1000124 if (req_msg_len > INT_MAX ||
125 pldm_socket_sndbuf_accomodate(&(af_mctp->socket_send_buf),
126 (int)req_msg_len)) {
127 return PLDM_REQUESTER_SEND_FAIL;
128 }
129
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100130 ssize_t rc = sendto(af_mctp->socket, pldm_req_msg, req_msg_len, 0,
131 (struct sockaddr *)&addr, sizeof(addr));
132 if (rc == -1) {
133 return PLDM_REQUESTER_SEND_FAIL;
134 }
135 return PLDM_REQUESTER_SUCCESS;
136}
137
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930138LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100139int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
140{
141 if (!ctx || *ctx) {
142 return -EINVAL;
143 }
144
145 struct pldm_transport_af_mctp *af_mctp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930146 calloc(1, sizeof(struct pldm_transport_af_mctp));
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100147 if (!af_mctp) {
148 return -ENOMEM;
149 }
150
151 af_mctp->transport.name = AF_MCTP_NAME;
152 af_mctp->transport.version = 1;
153 af_mctp->transport.recv = pldm_transport_af_mctp_recv;
154 af_mctp->transport.send = pldm_transport_af_mctp_send;
155 af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
156 if (af_mctp->socket == -1) {
157 free(af_mctp);
158 return -1;
159 }
Rashmica Gupta04273e92023-06-16 16:03:37 +1000160
161 if (pldm_socket_sndbuf_init(&af_mctp->socket_send_buf,
162 af_mctp->socket)) {
163 close(af_mctp->socket);
164 free(af_mctp);
165 return -1;
166 }
167
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100168 *ctx = af_mctp;
169 return 0;
170}
171
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930172LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100173void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
174{
175 if (!ctx) {
176 return;
177 }
178 close(ctx->socket);
179 free(ctx);
180}