blob: 0de6ce96ee6562cf1318fad988574d46a51d5c9f [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;
Eric Yang37ab29c2025-03-20 13:48:31 +0800189
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000190 while (!queuedMctpInfos.empty())
191 {
Eric Yang37ab29c2025-03-20 13:48:31 +0800192 bool terminusInitFailed = false;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000193 if (manager)
194 {
195 co_await manager->beforeDiscoverTerminus();
196 }
197
198 const MctpInfos& mctpInfos = queuedMctpInfos.front();
199 for (const auto& mctpInfo : mctpInfos)
200 {
Patrick Williams29d2f4a2024-07-13 16:44:15 -0500201 auto it = findTerminusPtr(mctpInfo);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000202 if (it == termini.end())
203 {
Chau Ly75e00422024-03-19 12:33:08 +0000204 mctpInfoAvailTable[mctpInfo] = true;
Eric Yang37ab29c2025-03-20 13:48:31 +0800205 auto rc = co_await initMctpTerminus(mctpInfo);
206 if (rc != PLDM_SUCCESS)
207 {
208 lg2::error(
209 "Failed to initialize terminus with EID {EID}, networkId {NETWORK}, response code {RC}.",
210 "EID", std::get<0>(mctpInfo), "NETWORK",
211 std::get<3>(mctpInfo), "RC", rc);
212 mctpInfoAvailTable.erase(mctpInfo);
213 terminusInitFailed = true;
214 continue;
215 }
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000216 }
Gilbert Cheneac61a42022-02-23 20:56:19 +0000217
218 /* Get TID of initialized terminus */
219 auto tid = toTid(mctpInfo);
220 if (!tid)
221 {
Eric Yang37ab29c2025-03-20 13:48:31 +0800222 lg2::error(
223 "Failed to get TID for terminus with EID {EID}, networkId {NETWORK}.",
224 "EID", std::get<0>(mctpInfo), "NETWORK",
225 std::get<3>(mctpInfo));
Chau Ly75e00422024-03-19 12:33:08 +0000226 mctpInfoAvailTable.erase(mctpInfo);
Eric Yang37ab29c2025-03-20 13:48:31 +0800227 terminusInitFailed = true;
228 continue;
Gilbert Cheneac61a42022-02-23 20:56:19 +0000229 }
230 addedTids.push_back(tid.value());
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000231 }
232
233 if (manager)
234 {
235 co_await manager->afterDiscoverTerminus();
236 }
237
Eric Yang37ab29c2025-03-20 13:48:31 +0800238 if (terminusInitFailed)
239 {
240 co_return PLDM_ERROR;
241 }
242
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000243 queuedMctpInfos.pop();
244 }
245
246 co_return PLDM_SUCCESS;
247}
248
249void TerminusManager::removeMctpTerminus(const MctpInfos& mctpInfos)
250{
251 // remove terminus
252 for (const auto& mctpInfo : mctpInfos)
253 {
Patrick Williams29d2f4a2024-07-13 16:44:15 -0500254 auto it = findTerminusPtr(mctpInfo);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000255 if (it == termini.end())
256 {
257 continue;
258 }
259
Gilbert Cheneac61a42022-02-23 20:56:19 +0000260 if (manager)
261 {
262 manager->stopSensorPolling(it->second->getTid());
263 }
264
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000265 unmapTid(it->first);
266 termini.erase(it);
Chau Ly75e00422024-03-19 12:33:08 +0000267 mctpInfoAvailTable.erase(mctpInfo);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000268 }
269}
270
271exec::task<int> TerminusManager::initMctpTerminus(const MctpInfo& mctpInfo)
272{
273 mctp_eid_t eid = std::get<0>(mctpInfo);
274 pldm_tid_t tid = 0;
275 bool isMapped = false;
276 auto rc = co_await getTidOverMctp(eid, &tid);
277 if (rc != PLDM_SUCCESS)
278 {
279 lg2::error("Failed to Get Terminus ID, error {ERROR}.", "ERROR", rc);
280 co_return PLDM_ERROR;
281 }
282
283 if (tid == PLDM_TID_RESERVED)
284 {
285 lg2::error("Terminus responses the reserved {TID}.", "TID", tid);
286 co_return PLDM_ERROR;
287 }
288
289 /* Terminus already has TID */
290 if (tid != PLDM_TID_UNASSIGNED)
291 {
292 /* TID is used by one discovered terminus */
293 auto it = termini.find(tid);
294 if (it != termini.end())
295 {
296 auto terminusMctpInfo = toMctpInfo(it->first);
297 /* The discovered terminus has the same MCTP Info */
298 if (terminusMctpInfo &&
299 (std::get<0>(terminusMctpInfo.value()) ==
300 std::get<0>(mctpInfo)) &&
301 (std::get<3>(terminusMctpInfo.value()) ==
302 std::get<3>(mctpInfo)))
303 {
304 co_return PLDM_SUCCESS;
305 }
306 else
307 {
308 /* ToDo:
309 * Maybe the terminus supports multiple medium interfaces
310 * Or the TID is used by other terminus.
311 * Check the UUID to confirm.
312 */
313 isMapped = false;
314 }
315 }
316 /* Use the terminus TID for mapping */
317 else
318 {
319 auto mappedTid = storeTerminusInfo(mctpInfo, tid);
320 if (!mappedTid)
321 {
322 lg2::error("Failed to store Terminus Info for terminus {TID}.",
323 "TID", tid);
324 co_return PLDM_ERROR;
325 }
326 isMapped = true;
327 }
328 }
329
330 if (!isMapped)
331 {
332 // Assigning a tid. If it has been mapped, mapTid()
333 // returns the tid assigned before.
334 auto mappedTid = mapTid(mctpInfo);
335 if (!mappedTid)
336 {
337 lg2::error("Failed to store Terminus Info for terminus {TID}.",
338 "TID", tid);
339 co_return PLDM_ERROR;
340 }
341
342 tid = mappedTid.value();
343 rc = co_await setTidOverMctp(eid, tid);
344 if (rc != PLDM_SUCCESS)
345 {
346 lg2::error("Failed to Set terminus TID, error{ERROR}.", "ERROR",
347 rc);
348 unmapTid(tid);
349 co_return rc;
350 }
351
352 if (rc != PLDM_SUCCESS && rc != PLDM_ERROR_UNSUPPORTED_PLDM_CMD)
353 {
354 lg2::error("Terminus {TID} does not support SetTID command.", "TID",
355 tid);
356 unmapTid(tid);
357 co_return rc;
358 }
359
360 if (termini.contains(tid))
361 {
362 // the terminus has been discovered before
363 co_return PLDM_SUCCESS;
364 }
365 }
366 /* Discovery the mapped terminus */
367 uint64_t supportedTypes = 0;
368 rc = co_await getPLDMTypes(tid, supportedTypes);
369 if (rc)
370 {
371 lg2::error("Failed to Get PLDM Types for terminus {TID}, error {ERROR}",
372 "TID", tid, "ERROR", rc);
Eric Yang1be20722024-10-28 21:34:39 +0800373 unmapTid(tid);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000374 co_return PLDM_ERROR;
375 }
376
377 try
378 {
Chaul Lyfdf61cc2025-01-22 07:55:45 +0000379 termini[tid] = std::make_shared<Terminus>(tid, supportedTypes, event);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000380 }
381 catch (const sdbusplus::exception_t& e)
382 {
383 lg2::error("Failed to create terminus manager for terminus {TID}",
384 "TID", tid);
Eric Yang1be20722024-10-28 21:34:39 +0800385 unmapTid(tid);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000386 co_return PLDM_ERROR;
387 }
388
389 uint8_t type = PLDM_BASE;
390 auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
391 std::vector<uint8_t> pldmCmds(size);
392 while ((type < PLDM_MAX_TYPES))
393 {
394 if (!termini[tid]->doesSupportType(type))
395 {
396 type++;
397 continue;
398 }
Thu Nguyen6e615622024-06-22 02:10:34 +0000399
400 ver32_t version{0xFF, 0xFF, 0xFF, 0xFF};
401 auto rc = co_await getPLDMVersion(tid, type, &version);
402 if (rc)
403 {
404 lg2::error(
405 "Failed to Get PLDM Version for terminus {TID}, PLDM Type {TYPE}, error {ERROR}",
406 "TID", tid, "TYPE", type, "ERROR", rc);
407 }
408 termini[tid]->setSupportedTypeVersions(type, version);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000409 std::vector<bitfield8_t> cmds(PLDM_MAX_CMDS_PER_TYPE / 8);
Thu Nguyen6e615622024-06-22 02:10:34 +0000410 rc = co_await getPLDMCommands(tid, type, version, cmds.data());
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000411 if (rc)
412 {
413 lg2::error(
414 "Failed to Get PLDM Commands for terminus {TID}, error {ERROR}",
415 "TID", tid, "ERROR", rc);
416 }
417
418 for (size_t i = 0; i < cmds.size(); i++)
419 {
420 auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + i;
421 if (idx >= pldmCmds.size())
422 {
423 lg2::error(
424 "Calculated index {IDX} out of bounds for pldmCmds, type {TYPE}, command index {CMD_IDX}",
425 "IDX", idx, "TYPE", type, "CMD_IDX", i);
426 continue;
427 }
428 pldmCmds[idx] = cmds[i].byte;
429 }
430 type++;
431 }
432 termini[tid]->setSupportedCommands(pldmCmds);
433
Kevin Tung502bd602025-08-01 10:05:47 +0800434 /* Use the MCTP target name as the default terminus name */
435 MctpInfoName mctpInfoName = std::get<4>(mctpInfo);
436 if (mctpInfoName.has_value())
437 {
438 lg2::info("Terminus {TID} has default Terminus Name {NAME}", "NAME",
439 mctpInfoName.value(), "TID", tid);
440 termini[tid]->setTerminusName(mctpInfoName.value());
441 }
442
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000443 co_return PLDM_SUCCESS;
444}
445
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400446exec::task<int> TerminusManager::sendRecvPldmMsgOverMctp(
447 mctp_eid_t eid, Request& request, const pldm_msg** responseMsg,
448 size_t* responseLen)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000449{
Thu Nguyen6b901e42024-07-10 15:21:10 +0700450 int rc = 0;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000451 try
452 {
Thu Nguyen6b901e42024-07-10 15:21:10 +0700453 std::tie(rc, *responseMsg, *responseLen) =
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000454 co_await handler.sendRecvMsg(eid, std::move(request));
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000455 }
456 catch (const sdbusplus::exception_t& e)
457 {
458 lg2::error(
Thu Nguyen6b901e42024-07-10 15:21:10 +0700459 "Send and Receive PLDM message over MCTP throw error - {ERROR}.",
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000460 "ERROR", e);
461 co_return PLDM_ERROR;
462 }
Thu Nguyen6b901e42024-07-10 15:21:10 +0700463 catch (const int& e)
Jerry C Chen2da113f2024-07-09 16:02:23 +0800464 {
Thu Nguyen6b901e42024-07-10 15:21:10 +0700465 lg2::error(
466 "Send and Receive PLDM message over MCTP throw int error - {ERROR}.",
467 "ERROR", e);
Jerry C Chen2da113f2024-07-09 16:02:23 +0800468 co_return PLDM_ERROR;
469 }
Thu Nguyen6b901e42024-07-10 15:21:10 +0700470
471 co_return rc;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000472}
473
474exec::task<int> TerminusManager::getTidOverMctp(mctp_eid_t eid, pldm_tid_t* tid)
475{
ManojKiran Eda22bcb072025-07-11 23:49:43 +0000476 auto instanceId = instanceIdDb.next(eid);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000477 Request request(sizeof(pldm_msg_hdr));
Pavithra Barithaya36b36932025-01-30 10:33:05 +0530478 auto requestMsg = new (request.data()) pldm_msg;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000479 auto rc = encode_get_tid_req(instanceId, requestMsg);
480 if (rc)
481 {
482 instanceIdDb.free(eid, instanceId);
483 lg2::error(
484 "Failed to encode request GetTID for endpoint ID {EID}, error {RC} ",
485 "EID", eid, "RC", rc);
486 co_return rc;
487 }
488
489 const pldm_msg* responseMsg = nullptr;
490 size_t responseLen = 0;
491 rc = co_await sendRecvPldmMsgOverMctp(eid, request, &responseMsg,
492 &responseLen);
493 if (rc)
494 {
495 lg2::error("Failed to send GetTID for Endpoint {EID}, error {RC}",
496 "EID", eid, "RC", rc);
497 co_return rc;
498 }
499
500 uint8_t completionCode = 0;
501 rc = decode_get_tid_resp(responseMsg, responseLen, &completionCode, tid);
502 if (rc)
503 {
504 lg2::error(
505 "Failed to decode response GetTID for Endpoint ID {EID}, error {RC} ",
506 "EID", eid, "RC", rc);
507 co_return rc;
508 }
509
510 if (completionCode != PLDM_SUCCESS)
511 {
512 lg2::error("Error : GetTID for Endpoint ID {EID}, complete code {CC}.",
513 "EID", eid, "CC", completionCode);
514 co_return rc;
515 }
516
517 co_return completionCode;
518}
519
520exec::task<int> TerminusManager::setTidOverMctp(mctp_eid_t eid, pldm_tid_t tid)
521{
ManojKiran Eda22bcb072025-07-11 23:49:43 +0000522 auto instanceId = instanceIdDb.next(eid);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000523 Request request(sizeof(pldm_msg_hdr) + sizeof(pldm_set_tid_req));
Pavithra Barithaya36b36932025-01-30 10:33:05 +0530524 auto requestMsg = new (request.data()) pldm_msg;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000525 auto rc = encode_set_tid_req(instanceId, tid, requestMsg);
526 if (rc)
527 {
528 instanceIdDb.free(eid, instanceId);
529 lg2::error(
530 "Failed to encode request SetTID for endpoint ID {EID}, error {RC} ",
531 "EID", eid, "RC", rc);
532 co_return rc;
533 }
534
535 const pldm_msg* responseMsg = nullptr;
536 size_t responseLen = 0;
537 rc = co_await sendRecvPldmMsgOverMctp(eid, request, &responseMsg,
538 &responseLen);
539 if (rc)
540 {
541 lg2::error("Failed to send SetTID for Endpoint {EID}, error {RC}",
542 "EID", eid, "RC", rc);
543 co_return rc;
544 }
545
Jayanth Othayoth7c14fc42024-12-17 10:24:47 -0600546 if (responseMsg == nullptr || responseLen != PLDM_SET_TID_RESP_BYTES)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000547 {
548 lg2::error(
549 "Failed to decode response SetTID for Endpoint ID {EID}, error {RC} ",
550 "EID", eid, "RC", rc);
551 co_return PLDM_ERROR_INVALID_LENGTH;
552 }
553
554 co_return responseMsg->payload[0];
555}
556
Patrick Williams366507c2025-02-03 14:28:01 -0500557exec::task<int> TerminusManager::getPLDMTypes(pldm_tid_t tid,
558 uint64_t& supportedTypes)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000559{
560 Request request(sizeof(pldm_msg_hdr));
Pavithra Barithaya36b36932025-01-30 10:33:05 +0530561 auto requestMsg = new (request.data()) pldm_msg;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000562 auto rc = encode_get_types_req(0, requestMsg);
563 if (rc)
564 {
565 lg2::error(
566 "Failed to encode request getPLDMTypes for terminus ID {TID}, error {RC} ",
567 "TID", tid, "RC", rc);
568 co_return rc;
569 }
570
571 const pldm_msg* responseMsg = nullptr;
572 size_t responseLen = 0;
573
574 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
575 if (rc)
576 {
577 lg2::error("Failed to send GetPLDMTypes for terminus {TID}, error {RC}",
578 "TID", tid, "RC", rc);
579 co_return rc;
580 }
581
582 uint8_t completionCode = 0;
583 bitfield8_t* types = reinterpret_cast<bitfield8_t*>(&supportedTypes);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400584 rc =
585 decode_get_types_resp(responseMsg, responseLen, &completionCode, types);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000586 if (rc)
587 {
588 lg2::error(
589 "Failed to decode response GetPLDMTypes for terminus ID {TID}, error {RC} ",
590 "TID", tid, "RC", rc);
591 co_return rc;
592 }
593
594 if (completionCode != PLDM_SUCCESS)
595 {
596 lg2::error(
597 "Error : GetPLDMTypes for terminus ID {TID}, complete code {CC}.",
598 "TID", tid, "CC", completionCode);
599 co_return rc;
600 }
601 co_return completionCode;
602}
603
Thu Nguyen6e615622024-06-22 02:10:34 +0000604exec::task<int> TerminusManager::getPLDMCommands(
605 pldm_tid_t tid, uint8_t type, ver32_t version, bitfield8_t* supportedCmds)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000606{
607 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES);
Pavithra Barithaya36b36932025-01-30 10:33:05 +0530608 auto requestMsg = new (request.data()) pldm_msg;
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000609
610 auto rc = encode_get_commands_req(0, type, version, requestMsg);
611 if (rc)
612 {
613 lg2::error(
614 "Failed to encode request GetPLDMCommands for terminus ID {TID}, error {RC} ",
615 "TID", tid, "RC", rc);
616 co_return rc;
617 }
618
619 const pldm_msg* responseMsg = nullptr;
620 size_t responseLen = 0;
621
622 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
623 if (rc)
624 {
625 lg2::error(
626 "Failed to send GetPLDMCommands message for terminus {TID}, error {RC}",
627 "TID", tid, "RC", rc);
628 co_return rc;
629 }
630
631 /* Process response */
632 uint8_t completionCode = 0;
633 rc = decode_get_commands_resp(responseMsg, responseLen, &completionCode,
634 supportedCmds);
635 if (rc)
636 {
637 lg2::error(
638 "Failed to decode response GetPLDMCommands for terminus ID {TID}, error {RC} ",
639 "TID", tid, "RC", rc);
640 co_return rc;
641 }
642
643 if (completionCode != PLDM_SUCCESS)
644 {
645 lg2::error(
646 "Error : GetPLDMCommands for terminus ID {TID}, complete code {CC}.",
647 "TID", tid, "CC", completionCode);
648 co_return rc;
649 }
650
651 co_return completionCode;
652}
653
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400654exec::task<int> TerminusManager::sendRecvPldmMsg(
655 pldm_tid_t tid, Request& request, const pldm_msg** responseMsg,
656 size_t* responseLen)
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000657{
658 /**
659 * Size of tidPool is `std::numeric_limits<pldm_tid_t>::max() + 1`
660 * tidPool[i] always exist
661 */
662 if (!tidPool[tid])
663 {
664 co_return PLDM_ERROR_NOT_READY;
665 }
666
667 if (!transportLayerTable.contains(tid))
668 {
669 co_return PLDM_ERROR_NOT_READY;
670 }
671
672 if (transportLayerTable[tid] != SupportedTransportLayer::MCTP)
673 {
674 co_return PLDM_ERROR_NOT_READY;
675 }
676
677 auto mctpInfo = toMctpInfo(tid);
678 if (!mctpInfo.has_value())
679 {
680 co_return PLDM_ERROR_NOT_READY;
681 }
682
Chau Ly75e00422024-03-19 12:33:08 +0000683 // There's a cost of maintaining another table to hold availability
684 // status as we can't ensure that it always synchronizes with the
685 // mctpInfoTable; std::map operator[] will insert a default of boolean
686 // which is false to the mctpInfoAvailTable if the mctpInfo key doesn't
687 // exist. Once we miss to initialize the availability of an available
688 // endpoint, it will drop all the messages to/from it.
689 if (!mctpInfoAvailTable[mctpInfo.value()])
690 {
691 co_return PLDM_ERROR_NOT_READY;
692 }
693
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000694 auto eid = std::get<0>(mctpInfo.value());
Pavithra Barithaya36b36932025-01-30 10:33:05 +0530695 auto requestMsg = new (request.data()) pldm_msg;
ManojKiran Eda22bcb072025-07-11 23:49:43 +0000696 requestMsg->hdr.instance_id = instanceIdDb.next(eid);
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000697 auto rc = co_await sendRecvPldmMsgOverMctp(eid, request, responseMsg,
698 responseLen);
699
Chau Ly8fa40db2024-04-02 09:32:01 +0000700 if (rc == PLDM_ERROR_NOT_READY)
701 {
702 // Call Recover() to check enpoint's availability
703 // Set endpoint's availability in mctpInfoTable to false in advance
704 // to prevent message forwarding through this endpoint while mctpd
705 // is checking the endpoint.
706 std::string endpointObjPath =
707 constructEndpointObjPath(mctpInfo.value());
708 pldm::utils::recoverMctpEndpoint(endpointObjPath);
709 updateMctpEndpointAvailability(mctpInfo.value(), false);
710 }
711
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000712 co_return rc;
713}
714
Thu Nguyen6e615622024-06-22 02:10:34 +0000715exec::task<int> TerminusManager::getPLDMVersion(pldm_tid_t tid, uint8_t type,
716 ver32_t* version)
717{
718 Request request(sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES);
719 auto requestMsg = new (request.data()) pldm_msg;
720
721 auto rc =
722 encode_get_version_req(0, 0, PLDM_GET_FIRSTPART, type, requestMsg);
723 if (rc)
724 {
725 lg2::error(
726 "Failed to encode request getPLDMVersion for terminus ID {TID}, error {RC} ",
727 "TID", tid, "RC", rc);
728 co_return rc;
729 }
730
731 const pldm_msg* responseMsg = nullptr;
732 size_t responseLen = 0;
733
734 rc = co_await sendRecvPldmMsg(tid, request, &responseMsg, &responseLen);
735 if (rc)
736 {
737 lg2::error(
738 "Failed to send getPLDMVersion message for terminus {TID}, error {RC}",
739 "TID", tid, "RC", rc);
740 co_return rc;
741 }
742
743 /* Process response */
744 uint8_t completionCode = 0;
745 uint8_t transferFlag = 0;
746 uint32_t transferHandle = 0;
747 rc = decode_get_version_resp(responseMsg, responseLen, &completionCode,
748 &transferHandle, &transferFlag, version);
749 if (rc)
750 {
751 lg2::error(
752 "Failed to decode response getPLDMVersion for terminus ID {TID}, error {RC} ",
753 "TID", tid, "RC", rc);
754 co_return rc;
755 }
756
757 if (completionCode != PLDM_SUCCESS)
758 {
759 lg2::error(
760 "Error : getPLDMVersion for terminus ID {TID}, complete code {CC}.",
761 "TID", tid, "CC", completionCode);
762 co_return completionCode;
763 }
764
765 co_return completionCode;
766}
767
Thu Nguyen38e12aa2025-01-21 22:47:56 +0000768std::optional<mctp_eid_t> TerminusManager::getActiveEidByName(
769 const std::string& terminusName)
770{
771 if (!termini.size() || terminusName.empty())
772 {
773 return std::nullopt;
774 }
775
776 for (auto& [tid, terminus] : termini)
777 {
778 if (!terminus)
779 {
780 continue;
781 }
782
783 auto tmp = terminus->getTerminusName();
784 if (!tmp || std::empty(*tmp) || *tmp != terminusName)
785 {
786 continue;
787 }
788
789 try
790 {
791 auto mctpInfo = toMctpInfo(tid);
792 if (!mctpInfo || !mctpInfoAvailTable[*mctpInfo])
793 {
794 return std::nullopt;
795 }
796
797 return std::get<0>(*mctpInfo);
798 }
799 catch (const std::exception& e)
800 {
801 return std::nullopt;
802 }
803 }
804
805 return std::nullopt;
806}
Gilbert Chen6c7fed42022-02-22 15:40:17 +0000807} // namespace platform_mc
808} // namespace pldm