1 #include "terminus_manager.hpp"
2
3 #include "manager.hpp"
4
5 #include <phosphor-logging/lg2.hpp>
6
7 PHOSPHOR_LOG2_USING;
8
9 namespace pldm
10 {
11 namespace platform_mc
12 {
13
toMctpInfo(const pldm_tid_t & tid)14 std::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
toTid(const MctpInfo & mctpInfo) const36 std::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) {
45 return (std::get<0>(v.second) == std::get<0>(mctpInfo)) &&
46 (std::get<3>(v.second) == std::get<3>(mctpInfo));
47 });
48 if (mctpInfoTableIt == mctpInfoTable.end())
49 {
50 return std::nullopt;
51 }
52 return mctpInfoTableIt->first;
53 }
54
storeTerminusInfo(const MctpInfo & mctpInfo,pldm_tid_t tid)55 std::optional<pldm_tid_t> TerminusManager::storeTerminusInfo(
56 const MctpInfo& mctpInfo, pldm_tid_t tid)
57 {
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
mapTid(const MctpInfo & mctpInfo)80 std::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) {
89 return (std::get<0>(v.second) == std::get<0>(mctpInfo)) &&
90 (std::get<3>(v.second) == std::get<3>(mctpInfo));
91 });
92 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
unmapTid(const pldm_tid_t & tid)107 bool 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
updateMctpEndpointAvailability(const MctpInfo & mctpInfo,Availability availability)128 void 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
constructEndpointObjPath(const MctpInfo & mctpInfo)143 std::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
discoverMctpTerminus(const MctpInfos & mctpInfos)151 void 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); }),
167 exec::default_task_context<void>(exec::inline_scheduler{}));
168 }
169
findTerminusPtr(const MctpInfo & mctpInfo)170 TerminiMapper::iterator TerminusManager::findTerminusPtr(
171 const MctpInfo& mctpInfo)
172 {
173 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 });
182
183 return foundIter;
184 }
185
discoverMctpTerminusTask()186 exec::task<int> TerminusManager::discoverMctpTerminusTask()
187 {
188 std::vector<pldm_tid_t> addedTids;
189 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 {
199 auto it = findTerminusPtr(mctpInfo);
200 if (it == termini.end())
201 {
202 mctpInfoAvailTable[mctpInfo] = true;
203 co_await initMctpTerminus(mctpInfo);
204 }
205
206 /* Get TID of initialized terminus */
207 auto tid = toTid(mctpInfo);
208 if (!tid)
209 {
210 mctpInfoAvailTable.erase(mctpInfo);
211 co_return PLDM_ERROR;
212 }
213 addedTids.push_back(tid.value());
214 }
215
216 if (manager)
217 {
218 co_await manager->afterDiscoverTerminus();
219 }
220
221 queuedMctpInfos.pop();
222 }
223
224 co_return PLDM_SUCCESS;
225 }
226
removeMctpTerminus(const MctpInfos & mctpInfos)227 void TerminusManager::removeMctpTerminus(const MctpInfos& mctpInfos)
228 {
229 // remove terminus
230 for (const auto& mctpInfo : mctpInfos)
231 {
232 auto it = findTerminusPtr(mctpInfo);
233 if (it == termini.end())
234 {
235 continue;
236 }
237
238 if (manager)
239 {
240 manager->stopSensorPolling(it->second->getTid());
241 }
242
243 unmapTid(it->first);
244 termini.erase(it);
245 mctpInfoAvailTable.erase(mctpInfo);
246 }
247 }
248
initMctpTerminus(const MctpInfo & mctpInfo)249 exec::task<int> TerminusManager::initMctpTerminus(const MctpInfo& mctpInfo)
250 {
251 mctp_eid_t eid = std::get<0>(mctpInfo);
252 pldm_tid_t tid = 0;
253 bool isMapped = false;
254 auto rc = co_await getTidOverMctp(eid, &tid);
255 if (rc != PLDM_SUCCESS)
256 {
257 lg2::error("Failed to Get Terminus ID, error {ERROR}.", "ERROR", rc);
258 co_return PLDM_ERROR;
259 }
260
261 if (tid == PLDM_TID_RESERVED)
262 {
263 lg2::error("Terminus responses the reserved {TID}.", "TID", tid);
264 co_return PLDM_ERROR;
265 }
266
267 /* Terminus already has TID */
268 if (tid != PLDM_TID_UNASSIGNED)
269 {
270 /* TID is used by one discovered terminus */
271 auto it = termini.find(tid);
272 if (it != termini.end())
273 {
274 auto terminusMctpInfo = toMctpInfo(it->first);
275 /* The discovered terminus has the same MCTP Info */
276 if (terminusMctpInfo &&
277 (std::get<0>(terminusMctpInfo.value()) ==
278 std::get<0>(mctpInfo)) &&
279 (std::get<3>(terminusMctpInfo.value()) ==
280 std::get<3>(mctpInfo)))
281 {
282 co_return PLDM_SUCCESS;
283 }
284 else
285 {
286 /* ToDo:
287 * Maybe the terminus supports multiple medium interfaces
288 * Or the TID is used by other terminus.
289 * Check the UUID to confirm.
290 */
291 isMapped = false;
292 }
293 }
294 /* Use the terminus TID for mapping */
295 else
296 {
297 auto mappedTid = storeTerminusInfo(mctpInfo, tid);
298 if (!mappedTid)
299 {
300 lg2::error("Failed to store Terminus Info for terminus {TID}.",
301 "TID", tid);
302 co_return PLDM_ERROR;
303 }
304 isMapped = true;
305 }
306 }
307
308 if (!isMapped)
309 {
310 // Assigning a tid. If it has been mapped, mapTid()
311 // returns the tid assigned before.
312 auto mappedTid = mapTid(mctpInfo);
313 if (!mappedTid)
314 {
315 lg2::error("Failed to store Terminus Info for terminus {TID}.",
316 "TID", tid);
317 co_return PLDM_ERROR;
318 }
319
320 tid = mappedTid.value();
321 rc = co_await setTidOverMctp(eid, tid);
322 if (rc != PLDM_SUCCESS)
323 {
324 lg2::error("Failed to Set terminus TID, error{ERROR}.", "ERROR",
325 rc);
326 unmapTid(tid);
327 co_return rc;
328 }
329
330 if (rc != PLDM_SUCCESS && rc != PLDM_ERROR_UNSUPPORTED_PLDM_CMD)
331 {
332 lg2::error("Terminus {TID} does not support SetTID command.", "TID",
333 tid);
334 unmapTid(tid);
335 co_return rc;
336 }
337
338 if (termini.contains(tid))
339 {
340 // the terminus has been discovered before
341 co_return PLDM_SUCCESS;
342 }
343 }
344 /* Discovery the mapped terminus */
345 uint64_t supportedTypes = 0;
346 rc = co_await getPLDMTypes(tid, supportedTypes);
347 if (rc)
348 {
349 lg2::error("Failed to Get PLDM Types for terminus {TID}, error {ERROR}",
350 "TID", tid, "ERROR", rc);
351 unmapTid(tid);
352 co_return PLDM_ERROR;
353 }
354
355 try
356 {
357 termini[tid] = std::make_shared<Terminus>(tid, supportedTypes, event);
358 }
359 catch (const sdbusplus::exception_t& e)
360 {
361 lg2::error("Failed to create terminus manager for terminus {TID}",
362 "TID", tid);
363 unmapTid(tid);
364 co_return PLDM_ERROR;
365 }
366
367 uint8_t type = PLDM_BASE;
368 auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
369 std::vector<uint8_t> pldmCmds(size);
370 while ((type < PLDM_MAX_TYPES))
371 {
372 if (!termini[tid]->doesSupportType(type))
373 {
374 type++;
375 continue;
376 }
377
378 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
379 auto rc = co_await getPLDMVersion(tid, type, &version);
380 if (rc)
381 {
382 lg2::error(
383 "Failed to Get PLDM Version for terminus {TID}, PLDM Type {TYPE}, error {ERROR}",
384 "TID", tid, "TYPE", type, "ERROR", rc);
385 }
386 termini[tid]->setSupportedTypeVersions(type, version);
387 std::vector<bitfield8_t> cmds(PLDM_MAX_CMDS_PER_TYPE / 8);
388 rc = co_await getPLDMCommands(tid, type, version, cmds.data());
389 if (rc)
390 {
391 lg2::error(
392 "Failed to Get PLDM Commands for terminus {TID}, error {ERROR}",
393 "TID", tid, "ERROR", rc);
394 }
395
396 for (size_t i = 0; i < cmds.size(); i++)
397 {
398 auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + i;
399 if (idx >= pldmCmds.size())
400 {
401 lg2::error(
402 "Calculated index {IDX} out of bounds for pldmCmds, type {TYPE}, command index {CMD_IDX}",
403 "IDX", idx, "TYPE", type, "CMD_IDX", i);
404 continue;
405 }
406 pldmCmds[idx] = cmds[i].byte;
407 }
408 type++;
409 }
410 termini[tid]->setSupportedCommands(pldmCmds);
411
412 co_return PLDM_SUCCESS;
413 }
414
sendRecvPldmMsgOverMctp(mctp_eid_t eid,Request & request,const pldm_msg ** responseMsg,size_t * responseLen)415 exec::task<int> TerminusManager::sendRecvPldmMsgOverMctp(
416 mctp_eid_t eid, Request& request, const pldm_msg** responseMsg,
417 size_t* responseLen)
418 {
419 int rc = 0;
420 try
421 {
422 std::tie(rc, *responseMsg, *responseLen) =
423 co_await handler.sendRecvMsg(eid, std::move(request));
424 }
425 catch (const sdbusplus::exception_t& e)
426 {
427 lg2::error(
428 "Send and Receive PLDM message over MCTP throw error - {ERROR}.",
429 "ERROR", e);
430 co_return PLDM_ERROR;
431 }
432 catch (const int& e)
433 {
434 lg2::error(
435 "Send and Receive PLDM message over MCTP throw int error - {ERROR}.",
436 "ERROR", e);
437 co_return PLDM_ERROR;
438 }
439
440 co_return rc;
441 }
442
getTidOverMctp(mctp_eid_t eid,pldm_tid_t * tid)443 exec::task<int> TerminusManager::getTidOverMctp(mctp_eid_t eid, pldm_tid_t* tid)
444 {
445 auto instanceId = instanceIdDb.next(eid);
446 Request request(sizeof(pldm_msg_hdr));
447 auto requestMsg = new (request.data()) pldm_msg;
448 auto rc = encode_get_tid_req(instanceId, requestMsg);
449 if (rc)
450 {
451 instanceIdDb.free(eid, instanceId);
452 lg2::error(
453 "Failed to encode request GetTID for endpoint ID {EID}, error {RC} ",
454 "EID", eid, "RC", rc);
455 co_return rc;
456 }
457
458 const pldm_msg* responseMsg = nullptr;
459 size_t responseLen = 0;
460 rc = co_await sendRecvPldmMsgOverMctp(eid, request, &responseMsg,
461 &responseLen);
462 if (rc)
463 {
464 lg2::error("Failed to send GetTID for Endpoint {EID}, error {RC}",
465 "EID", eid, "RC", rc);
466 co_return rc;
467 }
468
469 uint8_t completionCode = 0;
470 rc = decode_get_tid_resp(responseMsg, responseLen, &completionCode, tid);
471 if (rc)
472 {
473 lg2::error(
474 "Failed to decode response GetTID for Endpoint ID {EID}, error {RC} ",
475 "EID", eid, "RC", rc);
476 co_return rc;
477 }
478
479 if (completionCode != PLDM_SUCCESS)
480 {
481 lg2::error("Error : GetTID for Endpoint ID {EID}, complete code {CC}.",
482 "EID", eid, "CC", completionCode);
483 co_return rc;
484 }
485
486 co_return completionCode;
487 }
488
setTidOverMctp(mctp_eid_t eid,pldm_tid_t tid)489 exec::task<int> TerminusManager::setTidOverMctp(mctp_eid_t eid, pldm_tid_t tid)
490 {
491 auto instanceId = instanceIdDb.next(eid);
492 Request request(sizeof(pldm_msg_hdr) + sizeof(pldm_set_tid_req));
493 auto requestMsg = new (request.data()) pldm_msg;
494 auto rc = encode_set_tid_req(instanceId, tid, requestMsg);
495 if (rc)
496 {
497 instanceIdDb.free(eid, instanceId);
498 lg2::error(
499 "Failed to encode request SetTID for endpoint ID {EID}, error {RC} ",
500 "EID", eid, "RC", rc);
501 co_return rc;
502 }
503
504 const pldm_msg* responseMsg = nullptr;
505 size_t responseLen = 0;
506 rc = co_await sendRecvPldmMsgOverMctp(eid, request, &responseMsg,
507 &responseLen);
508 if (rc)
509 {
510 lg2::error("Failed to send SetTID for Endpoint {EID}, error {RC}",
511 "EID", eid, "RC", rc);
512 co_return rc;
513 }
514
515 if (responseMsg == nullptr || responseLen != PLDM_SET_TID_RESP_BYTES)
516 {
517 lg2::error(
518 "Failed to decode response SetTID for Endpoint ID {EID}, error {RC} ",
519 "EID", eid, "RC", rc);
520 co_return PLDM_ERROR_INVALID_LENGTH;
521 }
522
523 co_return responseMsg->payload[0];
524 }
525
getPLDMTypes(pldm_tid_t tid,uint64_t & supportedTypes)526 exec::task<int> TerminusManager::getPLDMTypes(pldm_tid_t tid,
527 uint64_t& supportedTypes)
528 {
529 Request request(sizeof(pldm_msg_hdr));
530 auto requestMsg = new (request.data()) pldm_msg;
531 auto rc = encode_get_types_req(0, requestMsg);
532 if (rc)
533 {
534 lg2::error(
535 "Failed to encode request getPLDMTypes for terminus ID {TID}, error {RC} ",
536 "TID", tid, "RC", rc);
537 co_return rc;
538 }
539
540 const pldm_msg* responseMsg = nullptr;
541 size_t responseLen = 0;
542
543 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
544 if (rc)
545 {
546 lg2::error("Failed to send GetPLDMTypes for terminus {TID}, error {RC}",
547 "TID", tid, "RC", rc);
548 co_return rc;
549 }
550
551 uint8_t completionCode = 0;
552 bitfield8_t* types = reinterpret_cast<bitfield8_t*>(&supportedTypes);
553 rc =
554 decode_get_types_resp(responseMsg, responseLen, &completionCode, types);
555 if (rc)
556 {
557 lg2::error(
558 "Failed to decode response GetPLDMTypes for terminus ID {TID}, error {RC} ",
559 "TID", tid, "RC", rc);
560 co_return rc;
561 }
562
563 if (completionCode != PLDM_SUCCESS)
564 {
565 lg2::error(
566 "Error : GetPLDMTypes for terminus ID {TID}, complete code {CC}.",
567 "TID", tid, "CC", completionCode);
568 co_return rc;
569 }
570 co_return completionCode;
571 }
572
getPLDMCommands(pldm_tid_t tid,uint8_t type,ver32_t version,bitfield8_t * supportedCmds)573 exec::task<int> TerminusManager::getPLDMCommands(
574 pldm_tid_t tid, uint8_t type, ver32_t version, bitfield8_t* supportedCmds)
575 {
576 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES);
577 auto requestMsg = new (request.data()) pldm_msg;
578
579 auto rc = encode_get_commands_req(0, type, version, requestMsg);
580 if (rc)
581 {
582 lg2::error(
583 "Failed to encode request GetPLDMCommands for terminus ID {TID}, error {RC} ",
584 "TID", tid, "RC", rc);
585 co_return rc;
586 }
587
588 const pldm_msg* responseMsg = nullptr;
589 size_t responseLen = 0;
590
591 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
592 if (rc)
593 {
594 lg2::error(
595 "Failed to send GetPLDMCommands message for terminus {TID}, error {RC}",
596 "TID", tid, "RC", rc);
597 co_return rc;
598 }
599
600 /* Process response */
601 uint8_t completionCode = 0;
602 rc = decode_get_commands_resp(responseMsg, responseLen, &completionCode,
603 supportedCmds);
604 if (rc)
605 {
606 lg2::error(
607 "Failed to decode response GetPLDMCommands for terminus ID {TID}, error {RC} ",
608 "TID", tid, "RC", rc);
609 co_return rc;
610 }
611
612 if (completionCode != PLDM_SUCCESS)
613 {
614 lg2::error(
615 "Error : GetPLDMCommands for terminus ID {TID}, complete code {CC}.",
616 "TID", tid, "CC", completionCode);
617 co_return rc;
618 }
619
620 co_return completionCode;
621 }
622
sendRecvPldmMsg(pldm_tid_t tid,Request & request,const pldm_msg ** responseMsg,size_t * responseLen)623 exec::task<int> TerminusManager::sendRecvPldmMsg(
624 pldm_tid_t tid, Request& request, const pldm_msg** responseMsg,
625 size_t* responseLen)
626 {
627 /**
628 * Size of tidPool is `std::numeric_limits<pldm_tid_t>::max() + 1`
629 * tidPool[i] always exist
630 */
631 if (!tidPool[tid])
632 {
633 co_return PLDM_ERROR_NOT_READY;
634 }
635
636 if (!transportLayerTable.contains(tid))
637 {
638 co_return PLDM_ERROR_NOT_READY;
639 }
640
641 if (transportLayerTable[tid] != SupportedTransportLayer::MCTP)
642 {
643 co_return PLDM_ERROR_NOT_READY;
644 }
645
646 auto mctpInfo = toMctpInfo(tid);
647 if (!mctpInfo.has_value())
648 {
649 co_return PLDM_ERROR_NOT_READY;
650 }
651
652 // There's a cost of maintaining another table to hold availability
653 // status as we can't ensure that it always synchronizes with the
654 // mctpInfoTable; std::map operator[] will insert a default of boolean
655 // which is false to the mctpInfoAvailTable if the mctpInfo key doesn't
656 // exist. Once we miss to initialize the availability of an available
657 // endpoint, it will drop all the messages to/from it.
658 if (!mctpInfoAvailTable[mctpInfo.value()])
659 {
660 co_return PLDM_ERROR_NOT_READY;
661 }
662
663 auto eid = std::get<0>(mctpInfo.value());
664 auto requestMsg = new (request.data()) pldm_msg;
665 requestMsg->hdr.instance_id = instanceIdDb.next(eid);
666 auto rc = co_await sendRecvPldmMsgOverMctp(eid, request, responseMsg,
667 responseLen);
668
669 if (rc == PLDM_ERROR_NOT_READY)
670 {
671 // Call Recover() to check enpoint's availability
672 // Set endpoint's availability in mctpInfoTable to false in advance
673 // to prevent message forwarding through this endpoint while mctpd
674 // is checking the endpoint.
675 std::string endpointObjPath =
676 constructEndpointObjPath(mctpInfo.value());
677 pldm::utils::recoverMctpEndpoint(endpointObjPath);
678 updateMctpEndpointAvailability(mctpInfo.value(), false);
679 }
680
681 co_return rc;
682 }
683
getPLDMVersion(pldm_tid_t tid,uint8_t type,ver32_t * version)684 exec::task<int> TerminusManager::getPLDMVersion(pldm_tid_t tid, uint8_t type,
685 ver32_t* version)
686 {
687 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES);
688 auto requestMsg = new (request.data()) pldm_msg;
689
690 auto rc =
691 encode_get_version_req(0, 0, PLDM_GET_FIRSTPART, type, requestMsg);
692 if (rc)
693 {
694 lg2::error(
695 "Failed to encode request getPLDMVersion for terminus ID {TID}, error {RC} ",
696 "TID", tid, "RC", rc);
697 co_return rc;
698 }
699
700 const pldm_msg* responseMsg = nullptr;
701 size_t responseLen = 0;
702
703 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
704 if (rc)
705 {
706 lg2::error(
707 "Failed to send getPLDMVersion message for terminus {TID}, error {RC}",
708 "TID", tid, "RC", rc);
709 co_return rc;
710 }
711
712 /* Process response */
713 uint8_t completionCode = 0;
714 uint8_t transferFlag = 0;
715 uint32_t transferHandle = 0;
716 rc = decode_get_version_resp(responseMsg, responseLen, &completionCode,
717 &transferHandle, &transferFlag, version);
718 if (rc)
719 {
720 lg2::error(
721 "Failed to decode response getPLDMVersion for terminus ID {TID}, error {RC} ",
722 "TID", tid, "RC", rc);
723 co_return rc;
724 }
725
726 if (completionCode != PLDM_SUCCESS)
727 {
728 lg2::error(
729 "Error : getPLDMVersion for terminus ID {TID}, complete code {CC}.",
730 "TID", tid, "CC", completionCode);
731 co_return completionCode;
732 }
733
734 co_return completionCode;
735 }
736
getActiveEidByName(const std::string & terminusName)737 std::optional<mctp_eid_t> TerminusManager::getActiveEidByName(
738 const std::string& terminusName)
739 {
740 if (!termini.size() || terminusName.empty())
741 {
742 return std::nullopt;
743 }
744
745 for (auto& [tid, terminus] : termini)
746 {
747 if (!terminus)
748 {
749 continue;
750 }
751
752 auto tmp = terminus->getTerminusName();
753 if (!tmp || std::empty(*tmp) || *tmp != terminusName)
754 {
755 continue;
756 }
757
758 try
759 {
760 auto mctpInfo = toMctpInfo(tid);
761 if (!mctpInfo || !mctpInfoAvailTable[*mctpInfo])
762 {
763 return std::nullopt;
764 }
765
766 return std::get<0>(*mctpInfo);
767 }
768 catch (const std::exception& e)
769 {
770 return std::nullopt;
771 }
772 }
773
774 return std::nullopt;
775 }
776 } // namespace platform_mc
777 } // namespace pldm
778