blob: bd1912cbee8b4fd9ff5e4abe402cf4f8fd14563b [file] [log] [blame]
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -05001#include "pldm_cmd_helper.hpp"
2
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +08003#include "libpldm/requester/pldm.h"
4
John Wang58a0e062019-11-08 15:38:15 +08005namespace pldmtool
6{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -05007
John Wang58a0e062019-11-08 15:38:15 +08008namespace helper
9{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050010/*
11 * print the input buffer
12 *
13 */
14void printBuffer(const std::vector<uint8_t>& buffer)
15{
16 std::ostringstream tempStream;
17 if (!buffer.empty())
18 {
19 for (int byte : buffer)
20 {
21 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
22 << " ";
23 }
24 }
John Wang58a0e062019-11-08 15:38:15 +080025 std::cout << tempStream.str() << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050026}
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050027/*
28 * Initialize the socket, send pldm command & recieve response from socket
29 *
30 */
31int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
32 std::vector<uint8_t>& responseMsg)
33{
34 const char devPath[] = "\0mctp-mux";
35 int returnCode = 0;
36
37 int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
38 if (-1 == sockFd)
39 {
40 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060041 std::cerr << "Failed to create the socket : RC = " << sockFd << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050042 return returnCode;
43 }
John Wang58a0e062019-11-08 15:38:15 +080044 std::cout << "Success in creating the socket : RC = " << sockFd
45 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050046
47 struct sockaddr_un addr
48 {
49 };
50 addr.sun_family = AF_UNIX;
51
52 memcpy(addr.sun_path, devPath, sizeof(devPath) - 1);
53
54 CustomFD socketFd(sockFd);
55 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
56 sizeof(devPath) + sizeof(addr.sun_family) - 1);
57 if (-1 == result)
58 {
59 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080060 std::cerr << "Failed to connect to socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -060061 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050062 return returnCode;
63 }
John Wang58a0e062019-11-08 15:38:15 +080064 std::cout << "Success in connecting to socket : RC = " << returnCode
65 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050066
67 auto pldmType = MCTP_MSG_TYPE_PLDM;
68 result = write(socketFd(), &pldmType, sizeof(pldmType));
69 if (-1 == result)
70 {
71 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080072 std::cerr << "Failed to send message type as pldm to mctp : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -060073 << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050074 return returnCode;
75 }
John Wang58a0e062019-11-08 15:38:15 +080076 std::cout << "Success in sending message type as pldm to mctp : RC = "
77 << returnCode << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050078
79 result = send(socketFd(), requestMsg.data(), requestMsg.size(), 0);
80 if (-1 == result)
81 {
82 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060083 std::cerr << "Write to socket failure : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050084 return returnCode;
85 }
John Wang58a0e062019-11-08 15:38:15 +080086 std::cout << "Write to socket successful : RC = " << result << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050087
88 // Read the response from socket
89 ssize_t peekedLength = recv(socketFd(), nullptr, 0, MSG_TRUNC | MSG_PEEK);
90 if (0 == peekedLength)
91 {
John Wang58a0e062019-11-08 15:38:15 +080092 std::cerr << "Socket is closed : peekedLength = " << peekedLength
Sampa Misraaa8ae722019-12-12 03:20:40 -060093 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050094 return returnCode;
95 }
96 else if (peekedLength <= -1)
97 {
98 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060099 std::cerr << "recv() system call failed : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500100 return returnCode;
101 }
102 else
103 {
104 // loopback response message
105 std::vector<uint8_t> loopBackRespMsg(peekedLength);
106 auto recvDataLength =
107 recv(socketFd(), reinterpret_cast<void*>(loopBackRespMsg.data()),
108 peekedLength, 0);
109 if (recvDataLength == peekedLength)
110 {
John Wang58a0e062019-11-08 15:38:15 +0800111 std::cout << "Total length:" << recvDataLength << std::endl;
112 std::cout << "Loopback response message:" << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500113 printBuffer(loopBackRespMsg);
114 }
115 else
116 {
John Wang58a0e062019-11-08 15:38:15 +0800117 std::cerr << "Failure to read peeked length packet : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -0600118 << returnCode << "\n";
119 std::cerr << "peekedLength: " << peekedLength << "\n";
120 std::cerr << "Total length: " << recvDataLength << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500121 return returnCode;
122 }
123
124 // Confirming on the first recv() the Request bit is set in
125 // pldm_msg_hdr struct. If set proceed with recv() or else, quit.
126 auto hdr = reinterpret_cast<const pldm_msg_hdr*>(&loopBackRespMsg[2]);
127 uint8_t request = hdr->request;
128 if (request == PLDM_REQUEST)
129 {
John Wang58a0e062019-11-08 15:38:15 +0800130 std::cout << "On first recv(),response == request : RC = "
131 << returnCode << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500132 ssize_t peekedLength =
133 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500134 responseMsg.resize(peekedLength);
135 recvDataLength =
136 recv(socketFd(), reinterpret_cast<void*>(responseMsg.data()),
137 peekedLength, 0);
138 if (recvDataLength == peekedLength)
139 {
John Wang58a0e062019-11-08 15:38:15 +0800140 std::cout << "Total length: " << recvDataLength << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500141 }
142 else
143 {
John Wang58a0e062019-11-08 15:38:15 +0800144 std::cerr << "Failure to read response length packet: length = "
Sampa Misraaa8ae722019-12-12 03:20:40 -0600145 << recvDataLength << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500146 return returnCode;
147 }
148 }
149 else
150 {
John Wang58a0e062019-11-08 15:38:15 +0800151 std::cerr << "On first recv(),request != response : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -0600152 << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500153 return returnCode;
154 }
155 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800156
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500157 returnCode = shutdown(socketFd(), SHUT_RDWR);
158 if (-1 == returnCode)
159 {
160 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +0800161 std::cerr << "Failed to shutdown the socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -0600162 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500163 return returnCode;
164 }
165
John Wang58a0e062019-11-08 15:38:15 +0800166 std::cout << "Shutdown Socket successful : RC = " << returnCode
167 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500168 return PLDM_SUCCESS;
169}
John Wang58a0e062019-11-08 15:38:15 +0800170
171void CommandInterface::exec()
172{
173 auto [rc, requestMsg] = createRequestMsg();
174 if (rc != PLDM_SUCCESS)
175 {
176 std::cerr << "Failed to encode request message for " << pldmType << ":"
Sampa Misraaa8ae722019-12-12 03:20:40 -0600177 << commandName << " rc = " << rc << "\n";
John Wang58a0e062019-11-08 15:38:15 +0800178 return;
179 }
180
181 std::cout << "Encode request successfully" << std::endl;
182
John Wangb754eee2020-02-15 16:10:25 +0800183 std::vector<uint8_t> responseMsg;
184 rc = pldmSendRecv(requestMsg, responseMsg);
185
186 if (rc != PLDM_SUCCESS)
187 {
188 std::cerr << "pldmSendRecv: Failed to receive RC = " << rc << "\n";
189 return;
190 }
191
192 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg.data());
193 parseResponseMsg(responsePtr, responseMsg.size() - sizeof(pldm_msg_hdr));
194}
195
196int CommandInterface::pldmSendRecv(std::vector<uint8_t>& requestMsg,
197 std::vector<uint8_t>& responseMsg)
198{
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800199 // Insert the PLDM message type and EID at the beginning of the
200 // msg.
John Wang58a0e062019-11-08 15:38:15 +0800201 requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800202 requestMsg.insert(requestMsg.begin(), mctp_eid);
John Wang58a0e062019-11-08 15:38:15 +0800203
204 std::cout << "Request Message:" << std::endl;
205 printBuffer(requestMsg);
206
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800207 if (mctp_eid != PLDM_ENTITY_ID)
John Wang58a0e062019-11-08 15:38:15 +0800208 {
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800209 int fd = pldm_open();
210 if (-1 == fd)
211 {
212 std::cerr << "failed to init mctp "
213 << "\n";
214 return -1;
215 }
216 uint8_t* responseMessage = nullptr;
217 size_t responseMessageSize{};
218 pldm_send_recv(mctp_eid, fd, requestMsg.data() + 2,
219 requestMsg.size() - 2, &responseMessage,
220 &responseMessageSize);
221 std::cout << "Response Message:" << std::endl;
222
223 responseMsg.resize(responseMessageSize);
224 memcpy(responseMsg.data(), responseMessage, responseMsg.size());
225
226 free(responseMessage);
227 printBuffer(responseMsg);
John Wang58a0e062019-11-08 15:38:15 +0800228 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800229 else
230 {
231 mctpSockSendRecv(requestMsg, responseMsg);
232 std::cout << "Response Message:" << std::endl;
233 printBuffer(responseMsg);
234 responseMsg.erase(responseMsg.begin(),
235 responseMsg.begin() + 2 /* skip the mctp header */);
236 }
John Wangb754eee2020-02-15 16:10:25 +0800237 return PLDM_SUCCESS;
John Wang58a0e062019-11-08 15:38:15 +0800238}
John Wang58a0e062019-11-08 15:38:15 +0800239} // namespace helper
Sampa Misraaa8ae722019-12-12 03:20:40 -0600240} // namespace pldmtool