blob: 0aacf339a5bc4cc65fd28e8f101589da29fd07d9 [file] [log] [blame]
Gilbert Chen6c7fed42022-02-22 15:40:17 +00001#include "terminus_manager.hpp"
2
3#include "manager.hpp"
4
5#include <phosphor-logging/lg2.hpp>
6
7PHOSPHOR_LOG2_USING;
8
9namespace pldm
10{
11namespace platform_mc
12{
13
14std::optional<MctpInfo> TerminusManager::toMctpInfo(const pldm_tid_t& tid)
15{
16 if (tid == PLDM_TID_UNASSIGNED || tid == PLDM_TID_RESERVED)
17 {
18 return std::nullopt;
19 }
20
21 if ((!this->transportLayerTable.contains(tid)) ||
22 (this->transportLayerTable[tid] != SupportedTransportLayer::MCTP))
23 {
24 return std::nullopt;
25 }
26
27 auto mctpInfoIt = mctpInfoTable.find(tid);
28 if (mctpInfoIt == mctpInfoTable.end())
29 {
30 return std::nullopt;
31 }
32
33 return mctpInfoIt->second;
34}
35
36std::optional<pldm_tid_t> TerminusManager::toTid(const MctpInfo& mctpInfo) const
37{
38 if (!pldm::utils::isValidEID(std::get<0>(mctpInfo)))
39 {
40 return std::nullopt;
41 }
42
43 auto mctpInfoTableIt = std::find_if(
44 mctpInfoTable.begin(), mctpInfoTable.end(), [&mctpInfo](auto& v) {
Patrick Williams16c2a0a2024-08-16 15:20:59 -040045 return (std::get<0>(v.second) == std::get<0>(mctpInfo)) &&
46 (std::get<3>(v.second) == std::get<3>(mctpInfo));
47 });
Gilbert Chen6c7fed42022-02-22 15:40:17 +000048 if (mctpInfoTableIt == mctpInfoTable.end())
49 {
50 return std::nullopt;
51 }
52 return mctpInfoTableIt->first;
53}
54
Patrick Williams366507c2025-02-03 14:28:01 -050055std::optional<pldm_tid_t> TerminusManager::storeTerminusInfo(
56 const MctpInfo& mctpInfo, pldm_tid_t tid)
Gilbert Chen6c7fed42022-02-22 15:40:17 +000057{
58 if (tid == PLDM_TID_UNASSIGNED || tid == PLDM_TID_RESERVED)
59 {
60 return std::nullopt;
61 }
62
63 if (!pldm::utils::isValidEID(std::get<0>(mctpInfo)))
64 {
65 return std::nullopt;
66 }
67
68 if (tidPool[tid])
69 {
70 return std::nullopt;
71 }
72
73 tidPool[tid] = true;
74 transportLayerTable[tid] = SupportedTransportLayer::MCTP;
75 mctpInfoTable[tid] = mctpInfo;
76
77 return tid;
78}
79
80std::optional<pldm_tid_t> TerminusManager::mapTid(const MctpInfo& mctpInfo)
81{
82 if (!pldm::utils::isValidEID(std::get<0>(mctpInfo)))
83 {
84 return std::nullopt;
85 }
86
87 auto mctpInfoTableIt = std::find_if(
88 mctpInfoTable.begin(), mctpInfoTable.end(), [&mctpInfo](auto& v) {
Patrick Williams16c2a0a2024-08-16 15:20:59 -040089 return (std::get<0>(v.second) == std::get<0>(mctpInfo)) &&
90 (std::get<3>(v.second) == std::get<3>(mctpInfo));
91 });
Gilbert Chen6c7fed42022-02-22 15:40:17 +000092 if (mctpInfoTableIt != mctpInfoTable.end())
93 {
94 return mctpInfoTableIt->first;
95 }
96
97 auto tidPoolIt = std::find(tidPool.begin(), tidPool.end(), false);
98 if (tidPoolIt == tidPool.end())
99 {
100 return std::nullopt;
101 }
102
103 pldm_tid_t tid = std::distance(tidPool.begin(), tidPoolIt);
104 return storeTerminusInfo(mctpInfo, tid);
105}
106
107bool TerminusManager::unmapTid(const pldm_tid_t& tid)
108{
109 if (tid == PLDM_TID_UNASSIGNED || tid == PLDM_TID_RESERVED)
110 {
111 return false;
112 }
113 tidPool[tid] = false;
114
115 if (transportLayerTable.contains(tid))
116 {
117 transportLayerTable.erase(tid);
118 }
119
120 if (mctpInfoTable.contains(tid))
121 {
122 mctpInfoTable.erase(tid);
123 }
124
125 return true;
126}
127
Chau Ly75e00422024-03-19 12:33:08 +0000128void TerminusManager::updateMctpEndpointAvailability(const MctpInfo& mctpInfo,
129 Availability availability)
130{
131 mctpInfoAvailTable.insert_or_assign(mctpInfo, availability);
132
133 if (manager)
134 {
135 auto tid = toTid(mctpInfo);
136 if (tid)
137 {
138 manager->updateAvailableState(tid.value(), availability);
139 }
140 }
141}
142
Chau Ly8fa40db2024-04-02 09:32:01 +0000143std::string TerminusManager::constructEndpointObjPath(const MctpInfo& mctpInfo)
144{
145 std::string eidStr = std::to_string(std::get<0>(mctpInfo));
146 std::string networkIDStr = std::to_string(std::get<3>(mctpInfo));
147 return std::format("{}/networks/{}/endpoints/{}", MCTPPath, networkIDStr,
148 eidStr);
149}
150
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000151void TerminusManager::discoverMctpTerminus(const MctpInfos& mctpInfos)
152{
153 queuedMctpInfos.emplace(mctpInfos);
154 if (discoverMctpTerminusTaskHandle.has_value())
155 {
156 auto& [scope, rcOpt] = *discoverMctpTerminusTaskHandle;
157 if (!rcOpt.has_value())
158 {
159 return;
160 }
161 stdexec::sync_wait(scope.on_empty());
162 discoverMctpTerminusTaskHandle.reset();
163 }
164 auto& [scope, rcOpt] = discoverMctpTerminusTaskHandle.emplace();
165 scope.spawn(discoverMctpTerminusTask() |
166 stdexec::then([&](int rc) { rcOpt.emplace(rc); }),
Patrick Williams61be7342024-07-30 16:55:33 -0500167 exec::default_task_context<void>(exec::inline_scheduler{}));
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000168}
169
Patrick Williams366507c2025-02-03 14:28:01 -0500170TerminiMapper::iterator TerminusManager::findTerminusPtr(
171 const MctpInfo& mctpInfo)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000172{
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400173 auto foundIter = std::find_if(
174 termini.begin(), termini.end(), [&](const auto& terminusPair) {
175 auto terminusMctpInfo = toMctpInfo(terminusPair.first);
176 return (terminusMctpInfo &&
177 (std::get<0>(terminusMctpInfo.value()) ==
178 std::get<0>(mctpInfo)) &&
179 (std::get<3>(terminusMctpInfo.value()) ==
180 std::get<3>(mctpInfo)));
181 });
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000182
183 return foundIter;
184}
185
186exec::task<int> TerminusManager::discoverMctpTerminusTask()
187{
Gilbert Cheneac61a42022-02-23 20:56:19 +0000188 std::vector<pldm_tid_t> addedTids;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000189 while (!queuedMctpInfos.empty())
190 {
191 if (manager)
192 {
193 co_await manager->beforeDiscoverTerminus();
194 }
195
196 const MctpInfos& mctpInfos = queuedMctpInfos.front();
197 for (const auto& mctpInfo : mctpInfos)
198 {
Patrick Williams29d2f4a2024-07-13 16:44:15 -0500199 auto it = findTerminusPtr(mctpInfo);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000200 if (it == termini.end())
201 {
Chau Ly75e00422024-03-19 12:33:08 +0000202 mctpInfoAvailTable[mctpInfo] = true;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000203 co_await initMctpTerminus(mctpInfo);
204 }
Gilbert Cheneac61a42022-02-23 20:56:19 +0000205
206 /* Get TID of initialized terminus */
207 auto tid = toTid(mctpInfo);
208 if (!tid)
209 {
Chau Ly75e00422024-03-19 12:33:08 +0000210 mctpInfoAvailTable.erase(mctpInfo);
Gilbert Cheneac61a42022-02-23 20:56:19 +0000211 co_return PLDM_ERROR;
212 }
213 addedTids.push_back(tid.value());
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000214 }
215
216 if (manager)
217 {
218 co_await manager->afterDiscoverTerminus();
Gilbert Cheneac61a42022-02-23 20:56:19 +0000219 for (const auto& tid : addedTids)
220 {
221 manager->startSensorPolling(tid);
222 }
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000223 }
224
225 queuedMctpInfos.pop();
226 }
227
228 co_return PLDM_SUCCESS;
229}
230
231void TerminusManager::removeMctpTerminus(const MctpInfos& mctpInfos)
232{
233 // remove terminus
234 for (const auto& mctpInfo : mctpInfos)
235 {
Patrick Williams29d2f4a2024-07-13 16:44:15 -0500236 auto it = findTerminusPtr(mctpInfo);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000237 if (it == termini.end())
238 {
239 continue;
240 }
241
Gilbert Cheneac61a42022-02-23 20:56:19 +0000242 if (manager)
243 {
244 manager->stopSensorPolling(it->second->getTid());
245 }
246
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000247 unmapTid(it->first);
248 termini.erase(it);
Chau Ly75e00422024-03-19 12:33:08 +0000249 mctpInfoAvailTable.erase(mctpInfo);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000250 }
251}
252
253exec::task<int> TerminusManager::initMctpTerminus(const MctpInfo& mctpInfo)
254{
255 mctp_eid_t eid = std::get<0>(mctpInfo);
256 pldm_tid_t tid = 0;
257 bool isMapped = false;
258 auto rc = co_await getTidOverMctp(eid, &tid);
259 if (rc != PLDM_SUCCESS)
260 {
261 lg2::error("Failed to Get Terminus ID, error {ERROR}.", "ERROR", rc);
262 co_return PLDM_ERROR;
263 }
264
265 if (tid == PLDM_TID_RESERVED)
266 {
267 lg2::error("Terminus responses the reserved {TID}.", "TID", tid);
268 co_return PLDM_ERROR;
269 }
270
271 /* Terminus already has TID */
272 if (tid != PLDM_TID_UNASSIGNED)
273 {
274 /* TID is used by one discovered terminus */
275 auto it = termini.find(tid);
276 if (it != termini.end())
277 {
278 auto terminusMctpInfo = toMctpInfo(it->first);
279 /* The discovered terminus has the same MCTP Info */
280 if (terminusMctpInfo &&
281 (std::get<0>(terminusMctpInfo.value()) ==
282 std::get<0>(mctpInfo)) &&
283 (std::get<3>(terminusMctpInfo.value()) ==
284 std::get<3>(mctpInfo)))
285 {
286 co_return PLDM_SUCCESS;
287 }
288 else
289 {
290 /* ToDo:
291 * Maybe the terminus supports multiple medium interfaces
292 * Or the TID is used by other terminus.
293 * Check the UUID to confirm.
294 */
295 isMapped = false;
296 }
297 }
298 /* Use the terminus TID for mapping */
299 else
300 {
301 auto mappedTid = storeTerminusInfo(mctpInfo, tid);
302 if (!mappedTid)
303 {
304 lg2::error("Failed to store Terminus Info for terminus {TID}.",
305 "TID", tid);
306 co_return PLDM_ERROR;
307 }
308 isMapped = true;
309 }
310 }
311
312 if (!isMapped)
313 {
314 // Assigning a tid. If it has been mapped, mapTid()
315 // returns the tid assigned before.
316 auto mappedTid = mapTid(mctpInfo);
317 if (!mappedTid)
318 {
319 lg2::error("Failed to store Terminus Info for terminus {TID}.",
320 "TID", tid);
321 co_return PLDM_ERROR;
322 }
323
324 tid = mappedTid.value();
325 rc = co_await setTidOverMctp(eid, tid);
326 if (rc != PLDM_SUCCESS)
327 {
328 lg2::error("Failed to Set terminus TID, error{ERROR}.", "ERROR",
329 rc);
330 unmapTid(tid);
331 co_return rc;
332 }
333
334 if (rc != PLDM_SUCCESS && rc != PLDM_ERROR_UNSUPPORTED_PLDM_CMD)
335 {
336 lg2::error("Terminus {TID} does not support SetTID command.", "TID",
337 tid);
338 unmapTid(tid);
339 co_return rc;
340 }
341
342 if (termini.contains(tid))
343 {
344 // the terminus has been discovered before
345 co_return PLDM_SUCCESS;
346 }
347 }
348 /* Discovery the mapped terminus */
349 uint64_t supportedTypes = 0;
350 rc = co_await getPLDMTypes(tid, supportedTypes);
351 if (rc)
352 {
353 lg2::error("Failed to Get PLDM Types for terminus {TID}, error {ERROR}",
354 "TID", tid, "ERROR", rc);
Eric Yang1be20722024-10-28 21:34:39 +0800355 unmapTid(tid);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000356 co_return PLDM_ERROR;
357 }
358
359 try
360 {
361 termini[tid] = std::make_shared<Terminus>(tid, supportedTypes);
362 }
363 catch (const sdbusplus::exception_t& e)
364 {
365 lg2::error("Failed to create terminus manager for terminus {TID}",
366 "TID", tid);
Eric Yang1be20722024-10-28 21:34:39 +0800367 unmapTid(tid);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000368 co_return PLDM_ERROR;
369 }
370
371 uint8_t type = PLDM_BASE;
372 auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
373 std::vector<uint8_t> pldmCmds(size);
374 while ((type < PLDM_MAX_TYPES))
375 {
376 if (!termini[tid]->doesSupportType(type))
377 {
378 type++;
379 continue;
380 }
Thu Nguyen6e615622024-06-22 02:10:34 +0000381
382 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
383 auto rc = co_await getPLDMVersion(tid, type, &version);
384 if (rc)
385 {
386 lg2::error(
387 "Failed to Get PLDM Version for terminus {TID}, PLDM Type {TYPE}, error {ERROR}",
388 "TID", tid, "TYPE", type, "ERROR", rc);
389 }
390 termini[tid]->setSupportedTypeVersions(type, version);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000391 std::vector<bitfield8_t> cmds(PLDM_MAX_CMDS_PER_TYPE / 8);
Thu Nguyen6e615622024-06-22 02:10:34 +0000392 rc = co_await getPLDMCommands(tid, type, version, cmds.data());
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000393 if (rc)
394 {
395 lg2::error(
396 "Failed to Get PLDM Commands for terminus {TID}, error {ERROR}",
397 "TID", tid, "ERROR", rc);
398 }
399
400 for (size_t i = 0; i < cmds.size(); i++)
401 {
402 auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + i;
403 if (idx >= pldmCmds.size())
404 {
405 lg2::error(
406 "Calculated index {IDX} out of bounds for pldmCmds, type {TYPE}, command index {CMD_IDX}",
407 "IDX", idx, "TYPE", type, "CMD_IDX", i);
408 continue;
409 }
410 pldmCmds[idx] = cmds[i].byte;
411 }
412 type++;
413 }
414 termini[tid]->setSupportedCommands(pldmCmds);
415
416 co_return PLDM_SUCCESS;
417}
418
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400419exec::task<int> TerminusManager::sendRecvPldmMsgOverMctp(
420 mctp_eid_t eid, Request& request, const pldm_msg** responseMsg,
421 size_t* responseLen)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000422{
Thu Nguyen6b901e42024-07-10 15:21:10 +0700423 int rc = 0;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000424 try
425 {
Thu Nguyen6b901e42024-07-10 15:21:10 +0700426 std::tie(rc, *responseMsg, *responseLen) =
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000427 co_await handler.sendRecvMsg(eid, std::move(request));
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000428 }
429 catch (const sdbusplus::exception_t& e)
430 {
431 lg2::error(
Thu Nguyen6b901e42024-07-10 15:21:10 +0700432 "Send and Receive PLDM message over MCTP throw error - {ERROR}.",
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000433 "ERROR", e);
434 co_return PLDM_ERROR;
435 }
Thu Nguyen6b901e42024-07-10 15:21:10 +0700436 catch (const int& e)
Jerry C Chen2da113f2024-07-09 16:02:23 +0800437 {
Thu Nguyen6b901e42024-07-10 15:21:10 +0700438 lg2::error(
439 "Send and Receive PLDM message over MCTP throw int error - {ERROR}.",
440 "ERROR", e);
Jerry C Chen2da113f2024-07-09 16:02:23 +0800441 co_return PLDM_ERROR;
442 }
Thu Nguyen6b901e42024-07-10 15:21:10 +0700443
444 co_return rc;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000445}
446
447exec::task<int> TerminusManager::getTidOverMctp(mctp_eid_t eid, pldm_tid_t* tid)
448{
449 auto instanceId = instanceIdDb.next(eid);
450 Request request(sizeof(pldm_msg_hdr));
451 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
452 auto rc = encode_get_tid_req(instanceId, requestMsg);
453 if (rc)
454 {
455 instanceIdDb.free(eid, instanceId);
456 lg2::error(
457 "Failed to encode request GetTID for endpoint ID {EID}, error {RC} ",
458 "EID", eid, "RC", rc);
459 co_return rc;
460 }
461
462 const pldm_msg* responseMsg = nullptr;
463 size_t responseLen = 0;
464 rc = co_await sendRecvPldmMsgOverMctp(eid, request, &responseMsg,
465 &responseLen);
466 if (rc)
467 {
468 lg2::error("Failed to send GetTID for Endpoint {EID}, error {RC}",
469 "EID", eid, "RC", rc);
470 co_return rc;
471 }
472
473 uint8_t completionCode = 0;
474 rc = decode_get_tid_resp(responseMsg, responseLen, &completionCode, tid);
475 if (rc)
476 {
477 lg2::error(
478 "Failed to decode response GetTID for Endpoint ID {EID}, error {RC} ",
479 "EID", eid, "RC", rc);
480 co_return rc;
481 }
482
483 if (completionCode != PLDM_SUCCESS)
484 {
485 lg2::error("Error : GetTID for Endpoint ID {EID}, complete code {CC}.",
486 "EID", eid, "CC", completionCode);
487 co_return rc;
488 }
489
490 co_return completionCode;
491}
492
493exec::task<int> TerminusManager::setTidOverMctp(mctp_eid_t eid, pldm_tid_t tid)
494{
495 auto instanceId = instanceIdDb.next(eid);
496 Request request(sizeof(pldm_msg_hdr) + sizeof(pldm_set_tid_req));
497 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
498 auto rc = encode_set_tid_req(instanceId, tid, requestMsg);
499 if (rc)
500 {
501 instanceIdDb.free(eid, instanceId);
502 lg2::error(
503 "Failed to encode request SetTID for endpoint ID {EID}, error {RC} ",
504 "EID", eid, "RC", rc);
505 co_return rc;
506 }
507
508 const pldm_msg* responseMsg = nullptr;
509 size_t responseLen = 0;
510 rc = co_await sendRecvPldmMsgOverMctp(eid, request, &responseMsg,
511 &responseLen);
512 if (rc)
513 {
514 lg2::error("Failed to send SetTID for Endpoint {EID}, error {RC}",
515 "EID", eid, "RC", rc);
516 co_return rc;
517 }
518
Jayanth Othayoth7c14fc42024-12-17 10:24:47 -0600519 if (responseMsg == nullptr || responseLen != PLDM_SET_TID_RESP_BYTES)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000520 {
521 lg2::error(
522 "Failed to decode response SetTID for Endpoint ID {EID}, error {RC} ",
523 "EID", eid, "RC", rc);
524 co_return PLDM_ERROR_INVALID_LENGTH;
525 }
526
527 co_return responseMsg->payload[0];
528}
529
Patrick Williams366507c2025-02-03 14:28:01 -0500530exec::task<int> TerminusManager::getPLDMTypes(pldm_tid_t tid,
531 uint64_t& supportedTypes)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000532{
533 Request request(sizeof(pldm_msg_hdr));
534 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
535 auto rc = encode_get_types_req(0, requestMsg);
536 if (rc)
537 {
538 lg2::error(
539 "Failed to encode request getPLDMTypes for terminus ID {TID}, error {RC} ",
540 "TID", tid, "RC", rc);
541 co_return rc;
542 }
543
544 const pldm_msg* responseMsg = nullptr;
545 size_t responseLen = 0;
546
547 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
548 if (rc)
549 {
550 lg2::error("Failed to send GetPLDMTypes for terminus {TID}, error {RC}",
551 "TID", tid, "RC", rc);
552 co_return rc;
553 }
554
555 uint8_t completionCode = 0;
556 bitfield8_t* types = reinterpret_cast<bitfield8_t*>(&supportedTypes);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400557 rc =
558 decode_get_types_resp(responseMsg, responseLen, &completionCode, types);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000559 if (rc)
560 {
561 lg2::error(
562 "Failed to decode response GetPLDMTypes for terminus ID {TID}, error {RC} ",
563 "TID", tid, "RC", rc);
564 co_return rc;
565 }
566
567 if (completionCode != PLDM_SUCCESS)
568 {
569 lg2::error(
570 "Error : GetPLDMTypes for terminus ID {TID}, complete code {CC}.",
571 "TID", tid, "CC", completionCode);
572 co_return rc;
573 }
574 co_return completionCode;
575}
576
Thu Nguyen6e615622024-06-22 02:10:34 +0000577exec::task<int> TerminusManager::getPLDMCommands(
578 pldm_tid_t tid, uint8_t type, ver32_t version, bitfield8_t* supportedCmds)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000579{
580 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES);
581 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000582
583 auto rc = encode_get_commands_req(0, type, version, requestMsg);
584 if (rc)
585 {
586 lg2::error(
587 "Failed to encode request GetPLDMCommands for terminus ID {TID}, error {RC} ",
588 "TID", tid, "RC", rc);
589 co_return rc;
590 }
591
592 const pldm_msg* responseMsg = nullptr;
593 size_t responseLen = 0;
594
595 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
596 if (rc)
597 {
598 lg2::error(
599 "Failed to send GetPLDMCommands message for terminus {TID}, error {RC}",
600 "TID", tid, "RC", rc);
601 co_return rc;
602 }
603
604 /* Process response */
605 uint8_t completionCode = 0;
606 rc = decode_get_commands_resp(responseMsg, responseLen, &completionCode,
607 supportedCmds);
608 if (rc)
609 {
610 lg2::error(
611 "Failed to decode response GetPLDMCommands for terminus ID {TID}, error {RC} ",
612 "TID", tid, "RC", rc);
613 co_return rc;
614 }
615
616 if (completionCode != PLDM_SUCCESS)
617 {
618 lg2::error(
619 "Error : GetPLDMCommands for terminus ID {TID}, complete code {CC}.",
620 "TID", tid, "CC", completionCode);
621 co_return rc;
622 }
623
624 co_return completionCode;
625}
626
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400627exec::task<int> TerminusManager::sendRecvPldmMsg(
628 pldm_tid_t tid, Request& request, const pldm_msg** responseMsg,
629 size_t* responseLen)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000630{
631 /**
632 * Size of tidPool is `std::numeric_limits<pldm_tid_t>::max() + 1`
633 * tidPool[i] always exist
634 */
635 if (!tidPool[tid])
636 {
637 co_return PLDM_ERROR_NOT_READY;
638 }
639
640 if (!transportLayerTable.contains(tid))
641 {
642 co_return PLDM_ERROR_NOT_READY;
643 }
644
645 if (transportLayerTable[tid] != SupportedTransportLayer::MCTP)
646 {
647 co_return PLDM_ERROR_NOT_READY;
648 }
649
650 auto mctpInfo = toMctpInfo(tid);
651 if (!mctpInfo.has_value())
652 {
653 co_return PLDM_ERROR_NOT_READY;
654 }
655
Chau Ly75e00422024-03-19 12:33:08 +0000656 // There's a cost of maintaining another table to hold availability
657 // status as we can't ensure that it always synchronizes with the
658 // mctpInfoTable; std::map operator[] will insert a default of boolean
659 // which is false to the mctpInfoAvailTable if the mctpInfo key doesn't
660 // exist. Once we miss to initialize the availability of an available
661 // endpoint, it will drop all the messages to/from it.
662 if (!mctpInfoAvailTable[mctpInfo.value()])
663 {
664 co_return PLDM_ERROR_NOT_READY;
665 }
666
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000667 auto eid = std::get<0>(mctpInfo.value());
668 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
669 requestMsg->hdr.instance_id = instanceIdDb.next(eid);
670 auto rc = co_await sendRecvPldmMsgOverMctp(eid, request, responseMsg,
671 responseLen);
672
Chau Ly8fa40db2024-04-02 09:32:01 +0000673 if (rc == PLDM_ERROR_NOT_READY)
674 {
675 // Call Recover() to check enpoint's availability
676 // Set endpoint's availability in mctpInfoTable to false in advance
677 // to prevent message forwarding through this endpoint while mctpd
678 // is checking the endpoint.
679 std::string endpointObjPath =
680 constructEndpointObjPath(mctpInfo.value());
681 pldm::utils::recoverMctpEndpoint(endpointObjPath);
682 updateMctpEndpointAvailability(mctpInfo.value(), false);
683 }
684
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000685 co_return rc;
686}
687
Thu Nguyen6e615622024-06-22 02:10:34 +0000688exec::task<int> TerminusManager::getPLDMVersion(pldm_tid_t tid, uint8_t type,
689 ver32_t* version)
690{
691 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES);
692 auto requestMsg = new (request.data()) pldm_msg;
693
694 auto rc =
695 encode_get_version_req(0, 0, PLDM_GET_FIRSTPART, type, requestMsg);
696 if (rc)
697 {
698 lg2::error(
699 "Failed to encode request getPLDMVersion for terminus ID {TID}, error {RC} ",
700 "TID", tid, "RC", rc);
701 co_return rc;
702 }
703
704 const pldm_msg* responseMsg = nullptr;
705 size_t responseLen = 0;
706
707 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
708 if (rc)
709 {
710 lg2::error(
711 "Failed to send getPLDMVersion message for terminus {TID}, error {RC}",
712 "TID", tid, "RC", rc);
713 co_return rc;
714 }
715
716 /* Process response */
717 uint8_t completionCode = 0;
718 uint8_t transferFlag = 0;
719 uint32_t transferHandle = 0;
720 rc = decode_get_version_resp(responseMsg, responseLen, &completionCode,
721 &transferHandle, &transferFlag, version);
722 if (rc)
723 {
724 lg2::error(
725 "Failed to decode response getPLDMVersion for terminus ID {TID}, error {RC} ",
726 "TID", tid, "RC", rc);
727 co_return rc;
728 }
729
730 if (completionCode != PLDM_SUCCESS)
731 {
732 lg2::error(
733 "Error : getPLDMVersion for terminus ID {TID}, complete code {CC}.",
734 "TID", tid, "CC", completionCode);
735 co_return completionCode;
736 }
737
738 co_return completionCode;
739}
740
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000741} // namespace platform_mc
742} // namespace pldm