blob: 5084f7d8d6af986736017e5bb2e3565530a763b0 [file] [log] [blame]
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301#include "config.h"
2#include "mctp-defines.h"
Rashmica Guptaba6971b2022-12-09 16:27:38 +11003#include "base.h"
4#include "container-of.h"
5#include "libpldm/pldm.h"
6#include "libpldm/transport.h"
7#include "transport.h"
8
9#include <errno.h>
10#include <linux/mctp.h>
11#include <poll.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/socket.h>
15#include <sys/types.h>
16#include <sys/un.h>
17#include <unistd.h>
18
19#define AF_MCTP_NAME "AF_MCTP"
20struct pldm_transport_af_mctp {
21 struct pldm_transport transport;
22 int socket;
23 pldm_tid_t tid_eid_map[MCTP_MAX_NUM_EID];
24};
25
26#define transport_to_af_mctp(ptr) \
27 container_of(ptr, struct pldm_transport_af_mctp, transport)
28
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093029LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +110030struct pldm_transport *
31pldm_transport_af_mctp_core(struct pldm_transport_af_mctp *ctx)
32{
33 return &ctx->transport;
34}
35
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093036LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +110037int pldm_transport_af_mctp_init_pollfd(struct pldm_transport *t,
38 struct pollfd *pollfd)
39{
40 struct pldm_transport_af_mctp *ctx = transport_to_af_mctp(t);
41 pollfd->fd = ctx->socket;
42 pollfd->events = POLLIN;
43 return 0;
44}
45
46static int pldm_transport_af_mctp_get_eid(struct pldm_transport_af_mctp *ctx,
47 pldm_tid_t tid, mctp_eid_t *eid)
48{
49 int i;
50 for (i = 0; i < MCTP_MAX_NUM_EID; i++) {
51 if (ctx->tid_eid_map[i] == tid) {
52 *eid = i;
53 return 0;
54 }
55 }
56 *eid = -1;
57 return -1;
58}
59
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093060LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +110061int pldm_transport_af_mctp_map_tid(struct pldm_transport_af_mctp *ctx,
62 pldm_tid_t tid, mctp_eid_t eid)
63{
64 ctx->tid_eid_map[eid] = tid;
65
66 return 0;
67}
68
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093069LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +110070int pldm_transport_af_mctp_unmap_tid(struct pldm_transport_af_mctp *ctx,
71 __attribute__((unused)) pldm_tid_t tid,
72 mctp_eid_t eid)
73{
74 ctx->tid_eid_map[eid] = 0;
75
76 return 0;
77}
78
79static pldm_requester_rc_t pldm_transport_af_mctp_recv(struct pldm_transport *t,
80 pldm_tid_t tid,
81 void **pldm_resp_msg,
82 size_t *resp_msg_len)
83{
84 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
85 mctp_eid_t eid = 0;
86 int rc = pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid);
87 if (rc) {
88 return PLDM_REQUESTER_RECV_FAIL;
89 }
90
91 ssize_t length = recv(af_mctp->socket, NULL, 0, MSG_PEEK | MSG_TRUNC);
92 if (length <= 0) {
93 return PLDM_REQUESTER_RECV_FAIL;
94 }
95 *pldm_resp_msg = malloc(length);
96 length = recv(af_mctp->socket, *pldm_resp_msg, length, MSG_TRUNC);
97 if (length < (ssize_t)sizeof(struct pldm_msg_hdr)) {
98 free(*pldm_resp_msg);
99 return PLDM_REQUESTER_INVALID_RECV_LEN;
100 }
101 *resp_msg_len = length;
102 return PLDM_REQUESTER_SUCCESS;
103}
104
105static pldm_requester_rc_t pldm_transport_af_mctp_send(struct pldm_transport *t,
106 pldm_tid_t tid,
107 const void *pldm_req_msg,
108 size_t req_msg_len)
109{
110 struct pldm_transport_af_mctp *af_mctp = transport_to_af_mctp(t);
111 mctp_eid_t eid = 0;
112 if (pldm_transport_af_mctp_get_eid(af_mctp, tid, &eid)) {
113 return PLDM_REQUESTER_SEND_FAIL;
114 }
115
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930116 struct sockaddr_mctp addr = { 0 };
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100117 addr.smctp_family = AF_MCTP;
118 addr.smctp_addr.s_addr = eid;
119 addr.smctp_type = MCTP_MSG_TYPE_PLDM;
120 addr.smctp_tag = MCTP_TAG_OWNER;
121
122 ssize_t rc = sendto(af_mctp->socket, pldm_req_msg, req_msg_len, 0,
123 (struct sockaddr *)&addr, sizeof(addr));
124 if (rc == -1) {
125 return PLDM_REQUESTER_SEND_FAIL;
126 }
127 return PLDM_REQUESTER_SUCCESS;
128}
129
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930130LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100131int pldm_transport_af_mctp_init(struct pldm_transport_af_mctp **ctx)
132{
133 if (!ctx || *ctx) {
134 return -EINVAL;
135 }
136
137 struct pldm_transport_af_mctp *af_mctp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930138 calloc(1, sizeof(struct pldm_transport_af_mctp));
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100139 if (!af_mctp) {
140 return -ENOMEM;
141 }
142
143 af_mctp->transport.name = AF_MCTP_NAME;
144 af_mctp->transport.version = 1;
145 af_mctp->transport.recv = pldm_transport_af_mctp_recv;
146 af_mctp->transport.send = pldm_transport_af_mctp_send;
147 af_mctp->socket = socket(AF_MCTP, SOCK_DGRAM, 0);
148 if (af_mctp->socket == -1) {
149 free(af_mctp);
150 return -1;
151 }
152 *ctx = af_mctp;
153 return 0;
154}
155
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930156LIBPLDM_ABI_TESTING
Rashmica Guptaba6971b2022-12-09 16:27:38 +1100157void pldm_transport_af_mctp_destroy(struct pldm_transport_af_mctp *ctx)
158{
159 if (!ctx) {
160 return;
161 }
162 close(ctx->socket);
163 free(ctx);
164}