LCOV - code coverage report
Current view: top level - coll_communicator_mgr/rank_info_detect - rank_info_detect_client.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.8 % 346 276
Test Date: 2026-07-28 12:11:00 Functions: 85.2 % 27 23

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include <thread>
      12              : #include <cstdlib>
      13              : #include <fstream>
      14              : #include <limits.h>
      15              : #include "rank_info_detect_client.h"
      16              : #include "root_handle_v2.h"
      17              : #include "env_config/env_config.h"
      18              : #include "host_buffer.h"
      19              : #include "binary_stream.h"
      20              : #include "hccp_peer_manager.h"
      21              : #include "orion_adapter_hccp.h"
      22              : #include "orion_adapter_rts.h"
      23              : #include "host_socket_handle_manager.h"
      24              : #include "socket_manager.h"
      25              : #include "topo_addr_info.h"
      26              : #include "adapter_error_manager_pub.h"
      27              : #include "phy_topo_builder.h"
      28              : #include "../../legacy/ascend950/framework/topo/rank_info_detect/preempt_port_manager.h"
      29              : 
      30              : namespace Hccl {
      31              : namespace {
      32              : constexpr u32 HOST_CONTROL_PORT_COUNT = 15;
      33              : 
      34            6 : std::string QueryTopoFilePathByDevice()
      35              : {
      36            6 :     const size_t bufSize = 1024;
      37            6 :     auto devLogicId = HrtGetDevice();
      38            6 :     auto devPhyId = HrtGetDevicePhyIdByIndex(devLogicId);
      39            6 :     std::vector<char> buffer(bufSize, '\0');
      40            6 :     int result = TopoAddrInfoGetTopoFilePath(devPhyId, buffer.data(), buffer.size());
      41            6 :     CHK_PRT_THROW(result != 0,
      42              :         HCCL_ERROR("[%s] Get topo file path failed.", __func__),
      43              :         InvalidParamsException, "Get topo file path failed.");
      44           12 :     return std::string(buffer.data());
      45            6 : }
      46              : 
      47            6 : void CheckTopoFilePath(const std::string &topoFilePath)
      48              : {
      49            6 :     char resolvedPath[PATH_MAX] = {0};
      50            6 :     CHK_PRT_THROW(realpath(topoFilePath.c_str(), resolvedPath) == nullptr,
      51              :         HCCL_ERROR("[%s] topo_file_path[%s] is not a valid real path", __func__, topoFilePath.c_str()),
      52              :         InvalidParamsException, "topo_file_path error");
      53            6 : }
      54              : 
      55            6 : std::string GetRootInfoTopoFilePath()
      56              : {
      57            6 :     std::string filePath = "/etc/hccl_rootinfo.json";
      58              :     JsonParser jsonParser{};
      59            6 :     nlohmann::json parseJson{};
      60            6 :     std::string topoFilePath{};
      61            6 :     std::ifstream file(filePath);
      62            6 :     if (file.good()) {
      63            0 :         jsonParser.ParseFileToJson(filePath, parseJson);
      64            0 :         std::string msgRankTopoFile = "error occurs when parser object of propName \"topo_file_path\"";
      65            0 :         TRY_CATCH_THROW(InvalidParamsException, msgRankTopoFile,
      66              :             topoFilePath = GetJsonProperty(parseJson, "topo_file_path"););
      67            0 :     } else {
      68            6 :         topoFilePath = QueryTopoFilePathByDevice();
      69              :     }
      70              : 
      71            6 :     CheckTopoFilePath(topoFilePath);
      72            6 :     return topoFilePath;
      73            6 : }
      74              : } // namespace
      75              : 
      76            0 : void RankInfoDetectClient::Setup(RankTableInfo &rankTable)
      77              : {
      78              :     // 1. 构造localRankTable
      79            0 :     RankTableInfo localRankTable{};
      80            0 :     ConstructRankTable(localRankTable);
      81              : 
      82              :     // 若启用单卡多进程抢占端口则执行
      83            0 :     SocketManager::ServerInitAll(localRankTable.ranks[0]);
      84            0 :     HostListenPortDetect(localRankTable.ranks[0]);
      85              : 
      86              :     // 2. 连接root节点
      87            0 :     Connect();
      88              : 
      89              :     // 3. 发送本端agentId和rankSize
      90            0 :     SendAgentIdAndRankSize();
      91              :     
      92              :     // 4. 发送给root节点
      93            0 :     SendLocalRankTable(localRankTable);
      94              :     
      95              :     // 5. 接收完整rankTable
      96            0 :     RecvRankTable();
      97            0 :     rankTable = rankTable_;
      98            0 : }
      99              : 
     100            0 : void RankInfoDetectClient::Connect()
     101              : {
     102            0 :     clientSocket_->Connect(); 
     103            0 :     CheckStatus();
     104            0 : }
     105              : 
     106            2 : void RankInfoDetectClient::CheckStatus()
     107              : {
     108            2 :     HCCL_DEBUG("[RankInfoDetectClient::%s] start.", __func__);
     109              : 
     110            2 :     auto startTime = std::chrono::steady_clock::now();
     111            2 :     auto timeout   = std::chrono::seconds(EnvConfig::GetInstance().GetSocketConfig().GetLinkTimeOut());
     112              : 
     113              :     while (true) {
     114       820265 :         bool isTimeout = ((std::chrono::steady_clock::now() - startTime) >= timeout);
     115       820265 :         if (isTimeout) {
     116            1 :             HCCL_ERROR("[RankInfoDetectClient::%s] get connected status socket timeout! timeout[%lld s]", __func__, timeout);
     117            7 :             RPT_INPUT_ERR(isTimeout, "EI0015", std::vector<std::string>({"error_reason"}),
     118              :                 std::vector<std::string>({StringFormat("Receiving message from the root node timed out "
     119              :                     "Timeout was set to %lld seconds. Check whether node rankId[%u] reports an error.",
     120              :                     static_cast<long long>(timeout.count()), rankId_)}));
     121              :             // 建链超时后,sleep 20s,避免上层应用提前退出,确保其他正常 client 能够收到 server 发出的临终遗言
     122            1 :             sleep(WAIT_ERROR_BROADCAST_TIME);
     123            1 :             THROW<TimeoutException>("client get connection timeout");
     124              :         }
     125              : 
     126       820264 :         if (clientSocket_->GetStatus() == SocketStatus::OK) {
     127            1 :             HCCL_DEBUG("[RankInfoDetectClient::%s] client get socket connection success.", __func__);
     128            1 :             break;
     129              :         }
     130       820263 :     }
     131              : 
     132            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end, connect ok.", __func__);
     133            2 : }
     134              : 
     135            1 : void RankInfoDetectClient::SendAgentIdAndRankSize()
     136              : {
     137            1 :     HCCL_DEBUG("[RankInfoDetectClient::%s] start.", __func__);
     138              : 
     139              :     // 发送agentId
     140            1 :     std::string rankID  = std::to_string(rankId_);
     141            1 :     std::string agentID = std::string(16 - rankID.length(), '0') + rankID;
     142            1 :     socketAgent_.SendMsg(agentID.c_str(), agentID.size());
     143              : 
     144              :     // 发送rankSize
     145            1 :     socketAgent_.SendMsg(&rankSize_, sizeof(rankSize_));
     146              : 
     147            1 :     HCCL_INFO("[RankInfoDetectClient::%s] send agentID[%s] and rankSize_[%u] end.", 
     148              :         __func__, agentID.c_str(), rankSize_);
     149            1 : }
     150              : 
     151            0 : void RankInfoDetectClient::SendLocalRankTable(const RankTableInfo &localRankTable)
     152              : {
     153            0 :     HCCL_DEBUG("[RankInfoDetectClient::%s] start.", __func__);
     154              : 
     155              :     // 消息格式: [ranktable数据(n字节)][step(4字节)]
     156            0 :     BinaryStream binaryStream;
     157            0 :     localRankTable.GetBinStream(true, binaryStream);
     158            0 :     binaryStream << currentStep_;
     159              : 
     160              :     // 字节流转换为vector<char>格式
     161            0 :     vector<char> sendMsg;
     162            0 :     binaryStream.Dump(sendMsg);
     163              : 
     164              :     // 发送
     165            0 :     socketAgent_.SendMsg(sendMsg.data(), sendMsg.size());
     166              : 
     167            0 :     HCCL_INFO("[RankInfoDetectClient::%s] end, currentStep_[%u].", __func__, currentStep_);
     168            0 :     currentStep_++;
     169            0 : }
     170              : 
     171            4 : void RankInfoDetectClient::ConstructSingleRank(RankTableInfo &localRankTable)
     172              : {
     173            4 :     localRankTable.version = "2.0";
     174            4 :     localRankTable.rankCount = 1;
     175            4 :     NewRankInfo rankInfo{};
     176            4 :     rankInfo.rankId = rankId_;
     177            4 :     rankInfo.rankLevelInfos.emplace_back(RankLevelInfo{});
     178            4 :     CHK_PRT_CONT(GetLocalTlsStatus(rankInfo.tlsStatus),
     179              :         HCCL_WARNING("[GetLocalTlsStatus] Can not get TlsStatus"));
     180            4 :     localRankTable.ranks.emplace_back(rankInfo);
     181              : 
     182              :     // 打印
     183            4 :     localRankTable.Dump();
     184            4 :     HCCL_INFO("[RankInfoDetectClient::%s] end, single rank, localRankTable[%s].", __func__, localRankTable.Describe().c_str());
     185            4 : }
     186              : 
     187            1 : void CheckRootInfoJson(const nlohmann::json &parseJson)
     188              : {
     189              :     // check version
     190            1 :     std::string version{};
     191            1 :     std::string msgVersion   = "error occurs when parser rootinfo object of propName \"version\"";
     192            1 :     TRY_CATCH_THROW(InvalidParamsException, msgVersion, version = GetJsonProperty(parseJson, "version"););
     193            1 :     if (version != "2.0") {
     194            0 :         RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
     195              :             std::vector<std::string>({version, "version", "2.0"}));
     196            0 :         HCCL_ERROR("[%s] failed with version [%s] is not \"2.0\".", __func__ , version.c_str());
     197            0 :         THROW<InvalidParamsException>("version error");
     198              :     }
     199              :     
     200              :     // parser topo_file_path
     201            1 :     std::string topoFilePath{};
     202            1 :     std::string msgRankTopoFile = "error occurs when parser object of propName \"topo_file_path\"";
     203            1 :     TRY_CATCH_THROW(InvalidParamsException, msgRankTopoFile, topoFilePath = GetJsonProperty(parseJson, "topo_file_path"););
     204              :     
     205              :     // check topo_file_path
     206            1 :     char resolvedPath[PATH_MAX] = {0};
     207            1 :     bool isInvalidPath = (realpath(topoFilePath.c_str(), resolvedPath) == nullptr);
     208            1 :     if (isInvalidPath) {
     209            0 :         RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
     210              :             std::vector<std::string>({topoFilePath, "topo_file_path", "valid path"}));
     211            0 :         HCCL_ERROR("[%s] topo_file_path[%s] is not a valid real path", __func__, topoFilePath.c_str());
     212            0 :         THROW<InvalidParamsException>("topo_file_path error");
     213              :     }
     214              : 
     215              :     // parser rank_count
     216            1 :     u32         rankCount{};
     217            1 :     std::string msgRankcount = "error occurs when parser object of propName \"rank_count\"";
     218            1 :     TRY_CATCH_THROW(InvalidParamsException, msgRankcount, rankCount = GetJsonPropertyUInt(parseJson, "rank_count"););
     219              :  
     220              :     // parser rank_list
     221            1 :     nlohmann::json rankJsons{};
     222            1 :     std::string    msgRanklist = "error occurs when parser object of propName \"rank_list\"";
     223            1 :     TRY_CATCH_THROW(InvalidParamsException, msgRanklist,
     224              :                          GetJsonPropertyList(parseJson, "rank_list", rankJsons););
     225              :     
     226              :     // check rank_count
     227            1 :     bool isRankCountMismatch = (rankCount != rankJsons.size());
     228            1 :     if (isRankCountMismatch) {
     229            0 :         RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
     230              :             std::vector<std::string>({std::to_string(rankCount), "rankCount", std::to_string(rankJsons.size())}));
     231            0 :         HCCL_ERROR("[%s] failed with rankCount is not equal to rank_list size."
     232              :             "rankCount[%u], ranks.size[%u]", __func__, rankCount, rankJsons.size());
     233            0 :         THROW<InvalidParamsException>("rankCount error");
     234              :     }
     235            1 : }
     236              : 
     237            1 : void RankInfoDetectClient::ConstructRankTable(RankTableInfo &localRankTable)
     238              : {
     239            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     240              : 
     241              :     // 单P场景处理
     242            1 :     CHK_PRT_RET((rankSize_ == 1), ConstructSingleRank(localRankTable),);
     243              : 
     244              :     // 1. 解析文件topoInfo.json
     245            1 :     std::string filePath = "/etc/hccl_rootinfo.json";
     246              :     JsonParser jsonParser{};
     247            1 :     nlohmann::json parseJson{};
     248            1 :     std::ifstream file(filePath);
     249            1 :     if (file.good()) {
     250            0 :         jsonParser.ParseFileToJson(filePath, parseJson);
     251              :     } else {
     252              :         size_t bufSize;
     253            1 :         s32 result = TopoAddrInfoGetSize(devPhyId_, &bufSize); // 获取rankInfo大小,用于提前分配内存
     254            1 :         CHK_PRT_THROW(result != 0 || bufSize > MAX_BUFFER_LEN,
     255              :                   HCCL_ERROR("[RankInfoDetectClient::%s] Get rankinfo size failed.", __func__),
     256              :                   InvalidParamsException, "Get rankinfo size failed.");
     257            1 :         std::vector<char> buffer(bufSize, '\0');
     258            1 :         result = TopoAddrInfoGet(devPhyId_, buffer.data(), &bufSize); // 获取rankInfo 并更新大小
     259            1 :         CHK_PRT_THROW(result != 0,
     260              :                   HCCL_ERROR("[RankInfoDetectClient::%s] Get rankinfo failed.", __func__),
     261              :                   InvalidParamsException, "Get rankinfo size failed.");
     262            1 :         std::string jsonString(buffer.data(), bufSize);
     263              :         // 将生成的info信息转换成json文件
     264            1 :         parseJson = nlohmann::json::parse(jsonString);
     265            1 :     }
     266            1 :     CheckRootInfoJson(parseJson);
     267              : 
     268              :     // 2. 获取当前devPhyId_对应的devInfo
     269            1 :     nlohmann::json localDevInfoJson{};
     270            1 :     GetLocalDevInfoJson(parseJson, localDevInfoJson);
     271              : 
     272              :     // 3. 组rankTable的json格式
     273            1 :     nlohmann::json localRankTableJson{};
     274            1 :     GetLocalRankTableJson(parseJson, localRankTableJson);
     275            1 :     localRankTableJson["rank_list"].push_back(localDevInfoJson); // 添加localDevInfoJson
     276              : 
     277              :     // 4. 反序列化获得RankTableInfo
     278            1 :     std::string msgDeserialize = "error occurs when localRankTable Deserialize";
     279            1 :     TRY_CATCH_THROW(InvalidParamsException, msgDeserialize, localRankTable.Deserialize(localRankTableJson, false););
     280              : 
     281            1 :     CHK_PRT_THROW(localRankTable.ranks.empty(),
     282              :         HCCL_ERROR("[RankInfoDetectClient::%s] local rank table has no rank.", __func__),
     283              :         InvalidParamsException, "local rank table has no rank");
     284            1 :     CHK_PRT_CONT(GetLocalTlsStatus(localRankTable.ranks[0].tlsStatus),
     285              :         HCCL_WARNING("[GetLocalTlsStatus] Can not get TlsStatus"));
     286            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     287            1 : }
     288              : 
     289            1 : void RankInfoDetectClient::GetLocalDevInfoJson(const nlohmann::json &parseJson, nlohmann::json &localDevInfoJson)
     290              : {
     291            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     292              : 
     293              :     // rankList字段对应json内容
     294            1 :     nlohmann::json rankJsons;
     295            1 :     std::string    msgRanklist = "error occurs when parser object of propName \"rank_list\"";
     296            1 :     TRY_CATCH_THROW(InvalidParamsException, msgRanklist,
     297              :                          GetJsonPropertyList(parseJson, "rank_list", rankJsons););
     298              :     
     299              :     // 获取localrankJsons, 匹配deviceId字段与当前devPhyId_匹配的内容
     300            1 :     for (auto &rankJson : rankJsons) {
     301            1 :         u32 devId = 0;
     302            1 :         std::string msgDeviceId = "error occurs when parser object of propName \"device_id\"";
     303            1 :         TRY_CATCH_THROW(InvalidParamsException, msgDeviceId,
     304              :             devId = GetJsonPropertyUInt(rankJson, "device_id");
     305              :         );
     306            1 :         if (devId == devPhyId_) {
     307            1 :             HCCL_INFO("[RankInfoDetectClient::%s] find localDevInfoJson.", __func__);
     308            1 :             localDevInfoJson = rankJson;
     309            1 :             break;
     310              :         }
     311            1 :     }
     312              : 
     313            1 :     if (localDevInfoJson.empty()) {
     314            0 :         HCCL_ERROR("[%s] failed, no device_id matches devPhyId_[%u] in rank_list.", __func__, devPhyId_);
     315              :     }
     316              : 
     317              :     // 添加rankId
     318            1 :     localDevInfoJson["rank_id"] = rankId_;
     319              : 
     320            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     321            1 : }
     322              : 
     323            1 : void RankInfoDetectClient::GetLocalRankTableJson(const nlohmann::json &parseJson, nlohmann::json &localRankTableJson)
     324              : {
     325            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     326              : 
     327            1 :     std::string version;
     328            1 :     std::string msgVersion  = "error occurs when parser object of propName \"version\"";
     329            1 :     TRY_CATCH_THROW(InvalidParamsException, msgVersion, version = GetJsonProperty(parseJson, "version"););
     330            1 :     localRankTableJson["version"] = version;
     331              : 
     332            1 :     std::string detour;
     333            1 :     std::string msgDetour = "error occurs when parser object of propName \"detour\"";
     334            1 :     TRY_CATCH_THROW(InvalidParamsException, msgDetour, detour = GetJsonProperty(parseJson, "detour", false););
     335            1 :     if (detour == "true") {
     336            0 :         localRankTableJson["detour"] = detour;
     337              :     }
     338              : 
     339            1 :     localRankTableJson["rank_count"] = rankSize_;
     340            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     341            1 : }
     342              : 
     343            1 : void RankInfoDetectClient::RecvRankTableMsg(vector<char> &rankInfoMsg)
     344              : {
     345            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     346              : 
     347              :     // 接收数据
     348            1 :     u64 revMsgLen = 0;
     349            1 :     std::unique_ptr<HostBuffer> msg = std::make_unique<HostBuffer>(MAX_BUFFER_LEN);
     350            1 :     char *msgAddr = reinterpret_cast<char *>(msg->GetAddr());
     351            1 :     CHK_PRT_THROW(!socketAgent_.RecvMsg(msgAddr, revMsgLen),
     352              :         HCCL_ERROR("RankInfoDetectClient::%s, recv rankTable error.", __func__),
     353              :         SocketException, "client recv fail");
     354              : 
     355              :     // 以vector<char>格式保存
     356            1 :     rankInfoMsg.resize(revMsgLen);
     357            1 :     rankInfoMsg.assign(msgAddr, msgAddr + revMsgLen);
     358              : 
     359            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end, revMsgLen[%llu].", __func__, revMsgLen);
     360            1 : }
     361              : 
     362              : // 解析接收到的rank table信息
     363            1 : void RankInfoDetectClient::ParseRankTable(vector<char> &rankInfoMsg)
     364              : {
     365            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     366              : 
     367              :     // 消息格式: [ranktable大小(u32, 4字节)][ranktable数据(n字节)][step(4字节)][failedAgentIdList]
     368            1 :     BinaryStream binStream(rankInfoMsg);
     369              : 
     370              :     // 解析localRankInfo
     371            1 :     rankTable_ = RankTableInfo(binStream);
     372            1 :     rankTable_.Dump();
     373              : 
     374              :     // 解析step
     375              :     u32 receivedStep;
     376            1 :     binStream >> receivedStep;
     377              : 
     378              :     // 解析failedAgentIdList
     379            1 :     std::string failedAgentIdList;
     380            1 :     binStream >> failedAgentIdList;
     381            1 :     if (failedAgentIdList.size() > 0) {
     382              :         // 建链失败时,打印 root 节点发来的临终遗言
     383            0 :         HCCL_ERROR("[RankInfoDetectClient::%s] TopoDetect ERROR occur, failedRankIdList[%s]",
     384              :                     __func__, failedAgentIdList.c_str());
     385              :     }
     386              : 
     387            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     388            1 : }
     389              : 
     390            1 : void RankInfoDetectClient::RecvRankTable()
     391              : {
     392              :     // 获取rankTable
     393            1 :     vector<char> rankInfoMsg{};
     394            1 :     RecvRankTableMsg(rankInfoMsg);
     395              : 
     396              :     // 解析rankTable
     397            1 :     ParseRankTable(rankInfoMsg);
     398              : 
     399              :     // 校验
     400            1 :     VerifyRankTable();
     401            1 : }
     402              : 
     403            0 : void RankInfoDetectClient::VerifyRankTable()
     404              : {
     405            0 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     406              : 
     407              :     // 校验rankCount符合预期
     408            0 :     if (rankTable_.rankCount != rankSize_) {
     409            0 :         THROW<InvalidParamsException>(StringFormat("[RankInfoDetectClient::%s] rank_count[%u] does not match"
     410              :             " rankSize_[%u].", __func__, rankTable_.rankCount, rankSize_));
     411              :     }
     412              : 
     413              :     // 校验rankTable内容
     414            0 :     rankTable_.Check();
     415              :     // TLS开关一致性校验
     416            0 :     HcclResult ret = VerifyTlsConsistency();
     417            0 :     CHK_PRT_THROW(ret != HCCL_SUCCESS,
     418              :         HCCL_ERROR("[RankInfoDetectClient::%s] tls consistency verify failed, ret[%d]", __func__, ret),
     419              :         InvalidParamsException, "tls consistency verify failed");
     420              : 
     421            0 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     422            0 : }
     423              : 
     424            5 : HcclResult RankInfoDetectClient::GetLocalTlsStatus(TlsStatus &tlsStatus) const
     425              : {
     426              :     struct RaInfo raInfo;
     427            5 :     raInfo.mode = NetworkMode::NETWORK_OFFLINE;
     428            5 :     raInfo.phyId = devPhyId_;
     429           10 :     return HrtRaGetTlsStatus(&raInfo, tlsStatus);
     430              : }
     431              : 
     432           12 : void RankInfoDetectClient::GenerateTlsStatusStr(
     433              :     std::string &tlsStatusStr, const std::vector<u32> &tlsStatusRanks) const
     434              : {
     435           12 :     tlsStatusStr.clear();
     436           23 :     for (const auto &rank : tlsStatusRanks) {
     437           11 :         tlsStatusStr += std::to_string(rank) + ",";
     438              :     }
     439           12 :     if (!tlsStatusStr.empty() && tlsStatusStr.back() == ',') {
     440            9 :         tlsStatusStr.pop_back();
     441              :     }
     442           12 : }
     443              : 
     444            2 : void RankInfoDetectClient::ReportTlsConfigurationError(const std::string &tlsInconsistentTlsType,
     445              :     const std::string &tlsEnableRankStr, const std::string &tlsDisableRankStr,
     446              :     const std::string &tlsUnknownRankStr) const
     447              : {
     448            2 :     std::string expectMessage = "\"All ranks are consistent. Current status: rankList for enabled tls: " +
     449            4 :         tlsEnableRankStr + "; rankList for disabled tls: " + tlsDisableRankStr +
     450            2 :         "; rankList for query failure tls: " + tlsUnknownRankStr + ".\"";
     451            4 :     std::string errormessage = "Value \"" + tlsInconsistentTlsType +
     452            2 :         "\" for config \"tls\" is invalid. Expected: " + expectMessage;
     453              : 
     454           28 :     RPT_INPUT_ERR(true,
     455              :         "EI0016",
     456              :         std::vector<std::string>({"value", "variable", "expect"}),
     457              :         std::vector<std::string>({tlsInconsistentTlsType, "\"tls\"", expectMessage}));
     458              : 
     459            2 :     HCCL_ERROR("[ReportTlsConfigurationError][RanktableCheck] %s", errormessage.c_str());
     460            6 : }
     461              : 
     462            5 : HcclResult RankInfoDetectClient::VerifyTlsConsistency() const
     463              : {
     464            5 :     bool isSupportCheckTlsStatus = true;     // 用于标识是否存在不支持查询Tls开关状态的情况
     465            5 :     bool isTlsConsistent = true;            // 用于标识TLS开关状态是否一致
     466            5 :     std::vector<u32> tlsEnableRank;
     467            5 :     std::vector<u32> tlsDisableRank;
     468            5 :     std::vector<u32> tlsUnknownRank;
     469              : 
     470           16 :     for (const auto &rankInfo : rankTable_.ranks) {
     471           11 :         if (rankInfo.tlsStatus == TlsStatus::ENABLE) {
     472            5 :             tlsEnableRank.push_back(rankInfo.rankId);
     473            6 :         } else if (rankInfo.tlsStatus == TlsStatus::DISABLE) {
     474            4 :             tlsDisableRank.push_back(rankInfo.rankId);
     475              :         } else {
     476            2 :             isSupportCheckTlsStatus = false;
     477            2 :             tlsUnknownRank.push_back(rankInfo.rankId);
     478              :         }
     479              :     }
     480              : 
     481              :     // 将卡的信息汇总成string
     482            5 :     std::string tlsEnableRankStr;
     483            5 :     std::string tlsDisableRankStr;
     484            5 :     std::string tlsUnknownRankStr;
     485            5 :     GenerateTlsStatusStr(tlsEnableRankStr, tlsEnableRank);
     486            5 :     GenerateTlsStatusStr(tlsDisableRankStr, tlsDisableRank);
     487            5 :     if (!isSupportCheckTlsStatus) {
     488            2 :         GenerateTlsStatusStr(tlsUnknownRankStr, tlsUnknownRank);
     489              :     }
     490              : 
     491            5 :     std::string tlsInconsistentTlsType;
     492            5 :     if (!tlsEnableRank.empty() && !tlsDisableRank.empty()) {
     493            2 :         isTlsConsistent = false;
     494            2 :         tlsInconsistentTlsType = (tlsDisableRank.size() <= tlsEnableRank.size()) ? "Disable" : "Enable";
     495              :     }
     496              : 
     497              :     // 四种不同情况
     498            5 :     if (isTlsConsistent && isSupportCheckTlsStatus) {
     499              :         // 1.通信域所有卡都支持查询TLS开关状态,并且TLS开关状态都是一致的。
     500            2 :         HCCL_INFO("[Verify][TlsConsistency] All ranks tlsStatus are consistent");
     501            3 :     } else if (!isTlsConsistent && isSupportCheckTlsStatus) {
     502              :         // 2.通信域所有卡都支持查询TLS开关状态,但是TLS开关状态存在不一致,报错。
     503            1 :         ReportTlsConfigurationError(
     504              :             tlsInconsistentTlsType, tlsEnableRankStr, tlsDisableRankStr, tlsUnknownRankStr);
     505            1 :         return HCCL_E_PARA;
     506            2 :     } else if (isTlsConsistent && !isSupportCheckTlsStatus) {
     507              :         // 3.通信域内的部分卡不支持查询TLS开关状态,目前能查询到的卡的TLS开关状态是一致的,打印warning提醒
     508            1 :         HCCL_WARNING("[Verify][TlsConsistency] Some ranks do not support to check tlsStatus, " \
     509              :             "not support rankId: [%s]", tlsUnknownRankStr.c_str());
     510              :     } else {
     511              :         // 4.通信域内的部分卡不支持查询TLS开关状态,但是目前能查询到的卡的TLS开关状态已经不一致,报错
     512            1 :         ReportTlsConfigurationError(
     513              :             tlsInconsistentTlsType, tlsEnableRankStr, tlsDisableRankStr, tlsUnknownRankStr);
     514            1 :         return HCCL_E_PARA;
     515              :     }
     516              : 
     517            3 :     return HCCL_SUCCESS;
     518            5 : }
     519              : 
     520            6 : void RankInfoDetectClient::HostListenPortDetect(NewRankInfo &rankInfo)
     521              : {
     522            6 :     std::string topoPath = GetRootInfoTopoFilePath();
     523            6 :     PhyTopoBuilder::GetInstance().Build(topoPath);
     524            6 :     auto devLogicId = HrtGetDevice();
     525            6 :     u32 devPhyId = rankInfo.deviceId;
     526           12 :     for (auto &rankLevelInfo : rankInfo.rankLevelInfos) {
     527            7 :         shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> graph = PhyTopo::GetInstance()->GetTopoGraph(rankLevelInfo.netLayer);
     528            7 :         if (graph == nullptr) {
     529            4 :             HCCL_DEBUG("[RankInfoDetectClient::%s]Can't find the layout %u Graph!", __func__, rankLevelInfo.netLayer);
     530            4 :             continue;
     531              :         }
     532            3 :         std::vector<std::shared_ptr<PhyTopo::Link>> links = graph->GetEdges(rankInfo.localId);
     533            5 :         for (auto &link : links) {
     534            3 :             if (link->GetSourceIFace()->GetPos() != AddrPosition::HOST) {
     535            1 :                 continue;
     536              :             }
     537            2 :             const std::set<LinkProtocol> &protocols = link->GetLinkProtocols();
     538            3 :             for (auto &protocol : protocols) {
     539            2 :                 LinkProtoType protoType = LinkProtocol2LinkProtoType(protocol);
     540            2 :                 if (protoType != LinkProtoType::RDMA || rankLevelInfo.rankAddrs.empty()) {
     541            1 :                     continue;
     542              :                 }
     543            1 :                 HCCL_DEBUG("[SocketManager::%s] find the host rdma link %s", __func__, link->Describe().c_str());
     544            1 :                 const IpAddress& hostIp = rankLevelInfo.rankAddrs[0].addr;
     545            1 :                 uint32_t hostPort = 0;
     546            1 :                 SetupHostListenPort(devLogicId, devPhyId, hostIp, hostPort);
     547            1 :                 rankInfo.hostPort = hostPort;
     548            1 :                 return;
     549              :             }
     550            2 :         }
     551            8 :     }
     552            6 : }
     553              : 
     554            1 : void RankInfoDetectClient::SetupHostListenPort(u32 devLogicId, u32 devPhyId, const IpAddress &hostIp, uint32_t &hostPort)
     555              : {
     556            1 :     std::lock_guard<std::mutex> lock(hostSocketLock_);
     557            1 :     u32 listenPort = HCCL_INVALID_PORT;
     558            1 :     auto portRange = EnvConfig::GetInstance().GetHostNicConfig().GetHostSocketPortRange();
     559            1 :     u32 basePort = EnvConfig::GetInstance().GetHostNicConfig().GetIfBasePort();
     560            1 :     if (portRange.empty() && basePort != HCCL_INVALID_PORT) {
     561            1 :         listenPort = basePort + devPhyId;
     562            1 :         HCCL_INFO("[RankInfoDetectClient::%s] BasePort is configured, listenPort[%u].", __func__, listenPort);
     563            1 :         hostPort = listenPort;
     564            1 :         return;
     565              :     }
     566              : 
     567            0 :     if (portRange.empty()) {
     568            0 :         constexpr u32 HOST_CONTROL_BASE_PORT = 60000;    // 控制面起始port
     569            0 :         HCCL_INFO("[RankInfoDetectClient::%s] No port configuration, using default port range[%u, %u]", __func__,
     570              :             HOST_CONTROL_BASE_PORT, HOST_CONTROL_BASE_PORT + HOST_CONTROL_PORT_COUNT);
     571            0 :         SocketPortRange defaultRange = {HOST_CONTROL_BASE_PORT, HOST_CONTROL_BASE_PORT + HOST_CONTROL_PORT_COUNT};
     572            0 :         portRange.push_back(defaultRange);
     573              :     }
     574              : 
     575            0 :     SocketHandle hostSocketHandle = HostSocketHandleManager::GetInstance().Create(devPhyId, hostIp);
     576            0 :     hostSocket_ = std::make_shared<Socket>(hostSocketHandle, hostIp, HCCL_INVALID_PORT, hostIp,
     577            0 :         "hostport_preempt", SocketRole::SERVER, NicType::HOST_NIC_TYPE);
     578            0 :     PreemptPortManager::GetInstance(devLogicId).ListenPreempt(hostSocket_, portRange, listenPort);
     579            0 :     HCCL_INFO("[RankInfoDetectClient::%s] preempt hostPort[%u] success.", __func__, listenPort);
     580            0 :     hostPort = listenPort;
     581            2 : }
     582              : 
     583           23 : void RankInfoDetectClient::SocketTearDown(u32 devPhyId)
     584              : {
     585           23 :     std::lock_guard<std::mutex> lock(hostSocketLock_);
     586           23 :     if (hostSocket_ == nullptr) {
     587           23 :         return;
     588              :     }
     589            0 :     const IpAddress& hostIp = hostSocket_->GetLocalIp();
     590            0 :     auto devLogicId = HrtGetDevice();
     591            0 :     if (EnvConfig::GetInstance().GetHostNicConfig().GetHostSocketPortRange().size() > 0 || 
     592            0 :         EnvConfig::GetInstance().GetHostNicConfig().GetIfBasePort() == HCCL_INVALID_PORT) {
     593              :         // 若开启抢占监听端口
     594            0 :         PreemptPortManager::GetInstance(devLogicId).Release(hostSocket_);
     595              :     }
     596            0 :     hostSocket_ = nullptr;
     597            0 :     HostSocketHandleManager::GetInstance().Destroy(devPhyId, hostIp);
     598           23 : }
     599              : 
     600           21 : void RankInfoDetectClient::TearDown()
     601              : {
     602           21 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     603           21 :     SocketTearDown(devPhyId_);
     604              :     
     605              :     // close socket
     606           21 :     clientSocket_->Close();
     607              :     
     608              :     // deinit handle
     609           21 :     HostSocketHandleManager::GetInstance().Destroy(devPhyId_, clientSocket_->GetLocalIp());
     610              : 
     611              :     // deinit ra in detach thread to avoid block main thread
     612           21 :     s32 deviceLogicId = HrtGetDevice();
     613           21 :     std::thread{[deviceLogicId](){
     614           21 :         EXCEPTION_CATCH(HccpPeerManager::GetInstance().DeInit(deviceLogicId),
     615              :             HCCL_ERROR("[RankInfoDetectClient::TearDown] DeInit exception"));
     616           42 :     }}.detach();
     617              : 
     618           21 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     619           21 : }
     620              : 
     621           22 : RankInfoDetectClient::~RankInfoDetectClient()
     622              : {
     623           22 :     DECTOR_TRY_CATCH("RankInfoDetectClient", TearDown());
     624           22 : }
     625              : 
     626              : }
        

Generated by: LCOV version 2.0-1