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