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: 88.8 % 474 421
Test Date: 2026-08-29 17:38:31 Functions: 92.3 % 39 36

            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_v2.h"
      18              : #include "host_buffer.h"
      19              : #include "binary_stream.h"
      20              : #include "hccp_peer_manager.h"
      21              : #include "hcomm_res.h"
      22              : #include "orion_adapter_hccp.h"
      23              : #include "orion_adapter_rts.h"
      24              : #include "host_socket_handle_manager.h"
      25              : #include "socket_manager.h"
      26              : #include "topo_addr_info.h"
      27              : #include "adapter_error_manager_pub.h"
      28              : #include "network_api_exception.h"
      29              : #include "phy_topo_builder.h"
      30              : #include "preempt_port_manager_v2.h"
      31              : 
      32              : namespace Hccl {
      33              : namespace {
      34              :     constexpr u32 HOST_CONTROL_PORT_COUNT = 15;
      35              :     constexpr u32 HOST_BACKUP_ADDR_NET_LAYER = 3;
      36              :     constexpr const char* BACKUP_ADDR_FIELD = "backup_addr";
      37              :     constexpr const char* ADDR_FIELD = "addr";
      38              :     constexpr const char* ADDR_TYPE_FIELD = "addr_type";
      39              : 
      40           43 :     void FillCommAddr(CommAddr& commAddr, const IpAddress& ipAddr)
      41              :     {
      42           43 :         const s32 family = ipAddr.GetFamily();
      43           43 :         if (family == AF_INET) {
      44           40 :             commAddr.type = COMM_ADDR_TYPE_IP_V4;
      45           40 :             commAddr.addr = ipAddr.GetBinaryAddress().addr;
      46            3 :         } else if (family == AF_INET6) {
      47            3 :             commAddr.type = COMM_ADDR_TYPE_IP_V6;
      48            3 :             commAddr.addr6 = ipAddr.GetBinaryAddress().addr6;
      49              :         } else {
      50            0 :             THROW<InvalidParamsException>(
      51            0 :                 StringFormat("[%s] invalid commAddrType, hostAddr[%s].", __func__, ipAddr.Describe().c_str()));
      52              :         }
      53           43 :     }
      54              : 
      55           18 :     void BuildHostAddrCandidates(const nlohmann::json& addrJson, std::vector<IpAddress>& candidates)
      56              :     {
      57              :         // 候选顺序固定为主地址在前、备地址按配置顺序在后,选择时取首个探测成功的地址。
      58           18 :         std::string addrType;
      59           18 :         std::string primaryAddr;
      60           18 :         const std::string msgAddrType = "get host addr_type failed";
      61           18 :         TRY_CATCH_THROW(InvalidParamsException, msgAddrType, addrType = GetJsonProperty(addrJson, ADDR_TYPE_FIELD););
      62           18 :         const std::string msgPrimaryAddr = "get primary host addr failed";
      63           18 :         TRY_CATCH_THROW(InvalidParamsException, msgPrimaryAddr, primaryAddr = GetJsonProperty(addrJson, ADDR_FIELD););
      64           18 :         IpAddress primaryIpAddress;
      65           18 :         const std::string msgParsePrimaryAddr = "parse primary host addr failed";
      66           19 :         TRY_CATCH_THROW(InvalidParamsException, msgParsePrimaryAddr,
      67              :                         AddressInfo::ParseAddrByType(addrType, primaryAddr, primaryIpAddress););
      68           17 :         candidates.clear();
      69           17 :         candidates.emplace_back(primaryIpAddress);
      70              : 
      71           17 :         std::vector<IpAddress> backupAddrs;
      72           17 :         AddressInfo::ParseBackupAddrs(addrJson.at(BACKUP_ADDR_FIELD), addrType, backupAddrs);
      73           13 :         candidates.insert(candidates.end(), backupAddrs.begin(), backupAddrs.end());
      74           42 :     }
      75              : 
      76           22 :     void CollectLayer3AddrJsons(nlohmann::json& localDevInfoJson, std::vector<nlohmann::json*>& addrJsons)
      77              :     {
      78              :         // 仅返回 netLayer3 及以上且配置了 backup_addr 的可写地址节点,其他地址直接沿用主 addr。
      79           22 :         addrJsons.clear();
      80           22 :         CHK_PRT_THROW(
      81              :             !localDevInfoJson.contains("level_list") || !localDevInfoJson.at("level_list").is_array(),
      82              :             HCCL_ERROR("[%s] level_list is missing or is not an array.", __func__), InvalidParamsException,
      83              :             "level_list is missing or is not an array");
      84           44 :         for (auto& levelJson : localDevInfoJson.at("level_list")) {
      85           22 :             if (!levelJson.contains("rank_addr_list") || !levelJson["rank_addr_list"].is_array()) {
      86            4 :                 continue;
      87              :             }
      88           44 :             u32 netLayer = 0;
      89           22 :             const std::string msgNetLayer = "get net_layer failed";
      90           22 :             TRY_CATCH_THROW(InvalidParamsException, msgNetLayer,
      91              :                             netLayer = GetJsonPropertyUInt(levelJson, "net_layer"););
      92           22 :             if (netLayer < HOST_BACKUP_ADDR_NET_LAYER) {
      93            4 :                 continue;
      94              :             }
      95           37 :             for (auto& addrJson : levelJson["rank_addr_list"]) {
      96           19 :                 if (!addrJson.contains(BACKUP_ADDR_FIELD)) {
      97            1 :                     HCCL_WARNING("[%s] backup_addr is not configured, use primary addr without probing.", __func__);
      98            1 :                     continue;
      99              :                 }
     100           18 :                 addrJsons.push_back(&addrJson);
     101              :             }
     102           22 :         }
     103           22 :     }
     104              : 
     105            6 :     std::string QueryTopoFilePathByDevice()
     106              :     {
     107            6 :         const size_t bufSize = 1024;
     108            6 :         auto devLogicId = HrtGetDevice();
     109            6 :         auto devPhyId = HrtGetDevicePhyIdByIndex(devLogicId);
     110            6 :         std::vector<char> buffer(bufSize, '\0');
     111            6 :         int result = TopoAddrInfoGetTopoFilePath(devPhyId, buffer.data(), buffer.size());
     112            6 :         CHK_PRT_THROW(
     113              :             result != 0, HCCL_ERROR("[%s] Get topo file path failed.", __func__), InvalidParamsException,
     114              :             "Get topo file path failed.");
     115           12 :         return std::string(buffer.data());
     116            6 :     }
     117              : 
     118            6 :     void CheckTopoFilePath(const std::string& topoFilePath)
     119              :     {
     120            6 :         char resolvedPath[PATH_MAX] = {0};
     121            6 :         CHK_PRT_THROW(
     122              :             realpath(topoFilePath.c_str(), resolvedPath) == nullptr,
     123              :             HCCL_ERROR("[%s] topo_file_path[%s] is not a valid real path", __func__, topoFilePath.c_str()),
     124              :             InvalidParamsException, "topo_file_path error");
     125            6 :     }
     126              : 
     127            6 :     std::string GetRootInfoTopoFilePath()
     128              :     {
     129            6 :         std::string filePath = "/etc/hccl_rootinfo.json";
     130              :         JsonParser jsonParser{};
     131            6 :         nlohmann::json parseJson{};
     132            6 :         std::string topoFilePath{};
     133            6 :         std::ifstream file(filePath);
     134            6 :         if (file.good()) {
     135            0 :             jsonParser.ParseFileToJson(filePath, parseJson);
     136            0 :             std::string msgRankTopoFile = "error occurs when parser object of propName \"topo_file_path\"";
     137            0 :             TRY_CATCH_THROW(InvalidParamsException, msgRankTopoFile,
     138              :                             topoFilePath = GetJsonProperty(parseJson, "topo_file_path"););
     139            0 :         } else {
     140            6 :             topoFilePath = QueryTopoFilePathByDevice();
     141              :         }
     142              : 
     143            6 :         CheckTopoFilePath(topoFilePath);
     144            6 :         return topoFilePath;
     145            6 :     }
     146              : } // namespace
     147              : 
     148            0 : void RankInfoDetectClient::Setup(RankTableInfo& rankTable)
     149              : {
     150              :     // 1. 构造localRankTable
     151            0 :     RankTableInfo localRankTable{};
     152            0 :     ConstructRankTable(localRankTable);
     153              : 
     154              :     // 若启用单卡多进程抢占端口则执行
     155            0 :     SocketManager::ServerInitAll(localRankTable.ranks[0]);
     156            0 :     HostListenPortDetect(localRankTable.ranks[0]);
     157              : 
     158              :     // 2. 连接root节点
     159            0 :     Connect();
     160              : 
     161              :     // 3. 发送本端agentId和rankSize
     162            0 :     SendAgentIdAndRankSize();
     163              : 
     164              :     // 4. 发送给root节点
     165            0 :     SendLocalRankTable(localRankTable);
     166              : 
     167              :     // 5. 接收完整rankTable
     168            0 :     RecvRankTable();
     169            0 :     rankTable = rankTable_;
     170            0 : }
     171              : 
     172            0 : void RankInfoDetectClient::Connect()
     173              : {
     174            0 :     clientSocket_->Connect();
     175            0 :     CheckStatus();
     176            0 : }
     177              : 
     178            2 : void RankInfoDetectClient::CheckStatus()
     179              : {
     180            2 :     HCCL_DEBUG("[RankInfoDetectClient::%s] start.", __func__);
     181              : 
     182            2 :     auto startTime = std::chrono::steady_clock::now();
     183            2 :     auto timeout = std::chrono::seconds(EnvConfig::GetInstance().GetSocketConfig().GetLinkTimeOut());
     184              : 
     185              :     while (true) {
     186       826865 :         bool isTimeout = ((std::chrono::steady_clock::now() - startTime) >= timeout);
     187       826865 :         if (isTimeout) {
     188            1 :             HCCL_ERROR(
     189              :                 "[RankInfoDetectClient::%s] get connected status socket timeout! timeout[%lld s]", __func__, timeout);
     190            7 :             RPT_INPUT_ERR(
     191              :                 isTimeout, "EI0015", std::vector<std::string>({"error_reason"}),
     192              :                 std::vector<std::string>({StringFormat(
     193              :                     "Receiving message from the root node timed out "
     194              :                     "Timeout was set to %lld seconds. Check whether node rankId[%u] reports an error.",
     195              :                     static_cast<long long>(timeout.count()), rankId_)}));
     196              :             // 建链超时后,sleep 20s,避免上层应用提前退出,确保其他正常 client 能够收到 server 发出的临终遗言
     197            1 :             sleep(WAIT_ERROR_BROADCAST_TIME);
     198            1 :             THROW<TimeoutException>("client get connection timeout");
     199              :         }
     200              : 
     201       826864 :         if (clientSocket_->GetStatus() == SocketStatus::OK) {
     202            1 :             HCCL_DEBUG("[RankInfoDetectClient::%s] client get socket connection success.", __func__);
     203            1 :             break;
     204              :         }
     205       826863 :     }
     206              : 
     207            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end, connect ok.", __func__);
     208            2 : }
     209              : 
     210            1 : void RankInfoDetectClient::SendAgentIdAndRankSize()
     211              : {
     212            1 :     HCCL_DEBUG("[RankInfoDetectClient::%s] start.", __func__);
     213              : 
     214              :     // 发送agentId
     215            1 :     std::string rankID = std::to_string(rankId_);
     216            1 :     std::string agentID = std::string(16 - rankID.length(), '0') + rankID;
     217            1 :     socketAgent_.SendMsg(agentID.c_str(), agentID.size());
     218              : 
     219              :     // 发送rankSize
     220            1 :     socketAgent_.SendMsg(&rankSize_, sizeof(rankSize_));
     221              : 
     222            1 :     HCCL_INFO(
     223              :         "[RankInfoDetectClient::%s] send agentID[%s] and rankSize_[%u] end.", __func__, agentID.c_str(), rankSize_);
     224            1 : }
     225              : 
     226            0 : void RankInfoDetectClient::SendLocalRankTable(const RankTableInfo& localRankTable)
     227              : {
     228            0 :     HCCL_DEBUG("[RankInfoDetectClient::%s] start.", __func__);
     229              : 
     230              :     // 消息格式: [ranktable数据(n字节)][step(4字节)]
     231            0 :     BinaryStream binaryStream;
     232            0 :     localRankTable.GetBinStream(true, binaryStream);
     233            0 :     binaryStream << currentStep_;
     234              : 
     235              :     // 字节流转换为vector<char>格式
     236            0 :     vector<char> sendMsg;
     237            0 :     binaryStream.Dump(sendMsg);
     238              : 
     239              :     // 发送
     240            0 :     socketAgent_.SendMsg(sendMsg.data(), sendMsg.size());
     241              : 
     242            0 :     HCCL_INFO("[RankInfoDetectClient::%s] end, currentStep_[%u].", __func__, currentStep_);
     243            0 :     currentStep_++;
     244            0 : }
     245              : 
     246            5 : void RankInfoDetectClient::ConstructSingleRank(RankTableInfo& localRankTable)
     247              : {
     248            5 :     localRankTable.version = "2.0";
     249            5 :     localRankTable.rankCount = 1;
     250            5 :     NewRankInfo rankInfo{};
     251            5 :     rankInfo.rankId = rankId_;
     252            5 :     rankInfo.rankLevelInfos.emplace_back(RankLevelInfo{});
     253            5 :     CHK_PRT_CONT(GetLocalTlsStatus(rankInfo.tlsStatus), HCCL_WARNING("[GetLocalTlsStatus] Can not get TlsStatus"));
     254            5 :     CHK_PRT_CONT(
     255              :         GetLocalHostDpuTlsStatus(rankInfo.hostDpuTlsStatus),
     256              :         HCCL_WARNING("[GetLocalHostDpuTlsStatus] Can not get Host DPU TlsStatus"));
     257            5 :     localRankTable.ranks.emplace_back(rankInfo);
     258              : 
     259              :     // 打印
     260            5 :     localRankTable.Dump();
     261            5 :     HCCL_INFO(
     262              :         "[RankInfoDetectClient::%s] end, single rank, localRankTable[%s].", __func__,
     263              :         localRankTable.Describe().c_str());
     264            5 : }
     265              : 
     266            1 : void CheckRootInfoJson(const nlohmann::json& parseJson)
     267              : {
     268              :     // check version
     269            1 :     std::string version{};
     270            1 :     std::string msgVersion = "error occurs when parser rootinfo object of propName \"version\"";
     271            1 :     TRY_CATCH_THROW(InvalidParamsException, msgVersion, version = GetJsonProperty(parseJson, "version"););
     272            1 :     if (version != "2.0") {
     273            0 :         RPT_INPUT_ERR(
     274              :             true, "EI0016", std::vector<std::string>({"value", "variable", "expect"}),
     275              :             std::vector<std::string>({version, "version", "2.0"}));
     276            0 :         HCCL_ERROR("[%s] failed with version [%s] is not \"2.0\".", __func__, version.c_str());
     277            0 :         THROW<InvalidParamsException>("version error");
     278              :     }
     279              : 
     280              :     // parser topo_file_path
     281            1 :     std::string topoFilePath{};
     282            1 :     std::string msgRankTopoFile = "error occurs when parser object of propName \"topo_file_path\"";
     283            1 :     TRY_CATCH_THROW(InvalidParamsException, msgRankTopoFile,
     284              :                     topoFilePath = GetJsonProperty(parseJson, "topo_file_path"););
     285              : 
     286              :     // check topo_file_path
     287            1 :     char resolvedPath[PATH_MAX] = {0};
     288            1 :     bool isInvalidPath = (realpath(topoFilePath.c_str(), resolvedPath) == nullptr);
     289            1 :     if (isInvalidPath) {
     290            0 :         RPT_INPUT_ERR(
     291              :             true, "EI0016", std::vector<std::string>({"value", "variable", "expect"}),
     292              :             std::vector<std::string>({topoFilePath, "topo_file_path", "valid path"}));
     293            0 :         HCCL_ERROR("[%s] topo_file_path[%s] is not a valid real path", __func__, topoFilePath.c_str());
     294            0 :         THROW<InvalidParamsException>("topo_file_path error");
     295              :     }
     296              : 
     297              :     // parser rank_count
     298            1 :     u32 rankCount{};
     299            1 :     std::string msgRankcount = "error occurs when parser object of propName \"rank_count\"";
     300            1 :     TRY_CATCH_THROW(InvalidParamsException, msgRankcount, rankCount = GetJsonPropertyUInt(parseJson, "rank_count"););
     301              : 
     302              :     // parser rank_list
     303            1 :     nlohmann::json rankJsons{};
     304            1 :     std::string msgRanklist = "error occurs when parser object of propName \"rank_list\"";
     305            1 :     TRY_CATCH_THROW(InvalidParamsException, msgRanklist, GetJsonPropertyList(parseJson, "rank_list", rankJsons););
     306              : 
     307              :     // check rank_count
     308            1 :     bool isRankCountMismatch = (rankCount != rankJsons.size());
     309            1 :     if (isRankCountMismatch) {
     310            0 :         RPT_INPUT_ERR(
     311              :             true, "EI0016", std::vector<std::string>({"value", "variable", "expect"}),
     312              :             std::vector<std::string>({std::to_string(rankCount), "rankCount", std::to_string(rankJsons.size())}));
     313            0 :         HCCL_ERROR(
     314              :             "[%s] failed with rankCount is not equal to rank_list size. "
     315              :             "rankCount[%u], ranks.size[%u]",
     316              :             __func__, rankCount, rankJsons.size());
     317            0 :         THROW<InvalidParamsException>("rankCount error");
     318              :     }
     319            1 : }
     320              : 
     321            1 : void RankInfoDetectClient::ConstructRankTable(RankTableInfo& localRankTable)
     322              : {
     323            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     324              : 
     325              :     // 单P场景处理
     326            1 :     CHK_PRT_RET((rankSize_ == 1), ConstructSingleRank(localRankTable), );
     327              : 
     328              :     // 1. 解析文件topoInfo.json
     329            1 :     std::string filePath = "/etc/hccl_rootinfo.json";
     330              :     JsonParser jsonParser{};
     331            1 :     nlohmann::json parseJson{};
     332            1 :     std::ifstream file(filePath);
     333            1 :     if (file.good()) {
     334            0 :         jsonParser.ParseFileToJson(filePath, parseJson);
     335              :     } else {
     336              :         size_t bufSize;
     337            1 :         s32 result = TopoAddrInfoGetSize(devPhyId_, &bufSize); // 获取rankInfo大小,用于提前分配内存
     338            1 :         CHK_PRT_THROW(
     339              :             result != 0 || bufSize > MAX_BUFFER_LEN,
     340              :             HCCL_ERROR("[RankInfoDetectClient::%s] Get rankinfo size failed.", __func__), InvalidParamsException,
     341              :             "Get rankinfo size failed.");
     342            1 :         std::vector<char> buffer(bufSize, '\0');
     343            1 :         result = TopoAddrInfoGet(devPhyId_, buffer.data(), &bufSize); // 获取rankInfo 并更新大小
     344            1 :         CHK_PRT_THROW(
     345              :             result != 0, HCCL_ERROR("[RankInfoDetectClient::%s] Get rankinfo failed.", __func__),
     346              :             InvalidParamsException, "Get rankinfo size failed.");
     347            1 :         std::string jsonString(buffer.data(), bufSize);
     348              :         // 将生成的info信息转换成json文件
     349            1 :         parseJson = nlohmann::json::parse(jsonString);
     350            1 :     }
     351            1 :     CheckRootInfoJson(parseJson);
     352              : 
     353              :     // 2. 获取当前devPhyId_对应的devInfo
     354            1 :     nlohmann::json localDevInfoJson{};
     355            1 :     GetLocalDevInfoJson(parseJson, localDevInfoJson);
     356              :     // 3. 在反序列化和上报本地 RankTable 前改写 addr,确保后续全局 RankTable 和 RankGraph 使用选中地址
     357            1 :     SelectLocalHostBackupAddr(localDevInfoJson);
     358              : 
     359              :     // 4. 组rankTable的json格式
     360            1 :     nlohmann::json localRankTableJson{};
     361            1 :     GetLocalRankTableJson(parseJson, localRankTableJson);
     362            1 :     localRankTableJson["rank_list"].push_back(localDevInfoJson); // 添加localDevInfoJson
     363              : 
     364              :     // 5. 反序列化获得RankTableInfo
     365            1 :     std::string msgDeserialize = "error occurs when localRankTable Deserialize";
     366            1 :     TRY_CATCH_THROW(InvalidParamsException, msgDeserialize, localRankTable.Deserialize(localRankTableJson, false););
     367              : 
     368            1 :     CHK_PRT_THROW(
     369              :         localRankTable.ranks.empty(), HCCL_ERROR("[RankInfoDetectClient::%s] local rank table has no rank.", __func__),
     370              :         InvalidParamsException, "local rank table has no rank");
     371            1 :     CHK_PRT_CONT(
     372              :         GetLocalTlsStatus(localRankTable.ranks[0].tlsStatus),
     373              :         HCCL_WARNING("[GetLocalTlsStatus] Can not get TlsStatus"));
     374            1 :     CHK_PRT_CONT(
     375              :         GetLocalHostDpuTlsStatus(localRankTable.ranks[0].hostDpuTlsStatus),
     376              :         HCCL_WARNING("[GetLocalHostDpuTlsStatus] Can not get Host DPU TlsStatus"));
     377            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     378            1 : }
     379              : 
     380           43 : void RankInfoDetectClient::ProbeHostRoceAddr(const IpAddress& hostAddr, bool& isAvailable) const
     381              : {
     382           43 :     isAvailable = false;
     383              :     // hostAddr 来自 netLayer3 的 rank_addr_list,是 RoCE 数据通信地址;它不同于 RootInfoDetect
     384              :     // 使用的 rootHandle.ip,后者只负责控制面 socket 建链。
     385           43 :     EndpointDesc endpointDesc{};
     386           43 :     const HcommResult initRet = EndpointDescInit(&endpointDesc, 1);
     387           43 :     CHK_PRT_THROW(
     388              :         initRet != HCCL_SUCCESS, HCCL_ERROR("[%s] EndpointDescInit failed, ret[%d].", __func__, initRet),
     389              :         InternalException, StringFormat("[%s] EndpointDescInit failed, ret[%d]", __func__, initRet));
     390           43 :     endpointDesc.protocol = COMM_PROTOCOL_ROCE;
     391           43 :     endpointDesc.loc.locType = ENDPOINT_LOC_TYPE_HOST;
     392           43 :     const std::string msgFillCommAddr = "fill host RoCE endpoint address failed";
     393           43 :     TRY_CATCH_THROW(InvalidParamsException, msgFillCommAddr, FillCommAddr(endpointDesc.commAddr, hostAddr););
     394              : 
     395           43 :     EndpointHandle endpointHandle = nullptr;
     396           43 :     const HcommResult createRet = HcommEndpointCreate(&endpointDesc, &endpointHandle);
     397              :     // 仅网络错误允许上层继续尝试备用地址,其他错误按不可恢复异常立即终止。
     398           43 :     if (createRet == HCCL_E_NETWORK) {
     399           29 :         HCCL_WARNING(
     400              :             "[%s] host addr is unavailable, hostAddr[%s], ret[%d].", __func__, hostAddr.Describe().c_str(), createRet);
     401           29 :         return;
     402           14 :     } else if (createRet != HCCL_SUCCESS) {
     403            2 :         HCCL_ERROR(
     404              :             "[%s] HcommEndpointCreate failed, hostAddr[%s], ret[%d].", __func__, hostAddr.Describe().c_str(),
     405              :             createRet);
     406            4 :         THROW<InternalException>(StringFormat("[%s] HcommEndpointCreate failed, ret[%d]", __func__, createRet));
     407              :     }
     408           12 :     if (endpointHandle != nullptr) {
     409              :         // Endpoint 仅用于可用性探测,不参与后续通信,探测成功后立即释放。
     410            3 :         const HcommResult destroyRet = HcommEndpointDestroy(endpointHandle);
     411            3 :         CHK_PRT_THROW(
     412              :             destroyRet != HCCL_SUCCESS,
     413              :             HCCL_ERROR(
     414              :                 "[%s] HcommEndpointDestroy failed, hostAddr[%s], ret[%d].", __func__, hostAddr.Describe().c_str(),
     415              :                 destroyRet),
     416              :             InternalException, StringFormat("[%s] HcommEndpointDestroy failed, ret[%d]", __func__, destroyRet));
     417              :     }
     418           11 :     isAvailable = true;
     419           11 :     HCCL_INFO(
     420              :         "[%s] host addr probe success, devPhyId[%u], rankId[%u], hostAddr[%s].", __func__, devPhyId_, rankId_,
     421              :         hostAddr.Describe().c_str());
     422           43 : }
     423              : 
     424           24 : void RankInfoDetectClient::SelectLocalHostBackupAddr(nlohmann::json& localDevInfoJson)
     425              : {
     426           48 :     const bool isLevelListInvalid = localDevInfoJson.empty() || !localDevInfoJson.contains("level_list")
     427           48 :                                     || !localDevInfoJson["level_list"].is_array();
     428           28 :     CHK_PRT_THROW(
     429              :         isLevelListInvalid,
     430              :         HCCL_ERROR(
     431              :             "[%s] level_list is missing or is not an array, devPhyId[%u], rankId[%u].", __func__, devPhyId_, rankId_),
     432              :         InvalidParamsException, "level_list is missing or is not an array");
     433           22 :     std::vector<nlohmann::json*> addrJsons;
     434           22 :     const std::string msgCollectLayer3Addr = "collect netLayer3 addr failed";
     435           22 :     TRY_CATCH_THROW(InvalidParamsException, msgCollectLayer3Addr, CollectLayer3AddrJsons(localDevInfoJson, addrJsons););
     436           22 :     if (addrJsons.empty()) {
     437            5 :         HCCL_DEBUG("[%s] no netLayer3+ addr with backup_addr needs probing.", __func__);
     438            5 :         return;
     439              :     }
     440              :     // 主备选择只依赖 RootInfo 的 net_layer 字段,不读取或构建 PhyTopo。
     441              :     // 对每个 netLayer3+ 地址独立探测主 addr;主地址不可用时,再按配置顺序逐个尝试 backup_addr。
     442           26 :     for (auto* addrJson : addrJsons) {
     443           18 :         SelectAvailableHostAddr(*addrJson);
     444              :     }
     445            8 :     HCCL_INFO(
     446              :         "[%s] end, devPhyId[%u], rankId[%u], addrConfigNum[%zu].", __func__, devPhyId_, rankId_, addrJsons.size());
     447           36 : }
     448              : 
     449           18 : void RankInfoDetectClient::SelectAvailableHostAddr(nlohmann::json& addrJson)
     450              : {
     451           18 :     std::vector<IpAddress> candidates;
     452           18 :     BuildHostAddrCandidates(addrJson, candidates);
     453           13 :     HCCL_INFO(
     454              :         "[%s] devPhyId[%u], rankId[%u], primaryAddr[%s], backupAddrSize[%zu], "
     455              :         "candidateSize[%zu].",
     456              :         __func__, devPhyId_, rankId_, candidates.front().Describe().c_str(), candidates.size() - 1, candidates.size());
     457              : 
     458              :     // HCCL_E_NETWORK 是可恢复错误,通过 isAvailable 继续尝试下一个候选地址;
     459              :     // 其他异常不在此处恢复。
     460           39 :     for (std::size_t idx = 0; idx < candidates.size(); ++idx) {
     461           39 :         bool isAvailable = false;
     462           39 :         ProbeHostRoceAddr(candidates[idx], isAvailable);
     463           37 :         if (isAvailable) {
     464            9 :             UpdateSelectedHostAddr(addrJson, candidates, idx);
     465            9 :             return;
     466              :         }
     467           28 :         if (idx == candidates.size() - 1) {
     468           28 :             RPT_INPUT_ERR(
     469              :                 true, "EI0016", std::vector<std::string>({"value", "variable", "expect"}),
     470              :                 std::vector<std::string>(
     471              :                     {candidates[idx].Describe(), "host addr candidates",
     472              :                      "at least one available host addr for rank connections"}));
     473            4 :             THROW<NetworkApiException>(StringFormat("[%s] all host addr candidates are unavailable", __func__));
     474              :         }
     475           26 :         HCCL_WARNING(
     476              :             "[%s] host addr is unavailable, try next candidate, "
     477              :             "devPhyId[%u], rankId[%u], candidateAddr[%s], candidateIndex[%zu].",
     478              :             __func__, devPhyId_, rankId_, candidates[idx].Describe().c_str(), idx);
     479              :     }
     480           22 : }
     481              : 
     482            9 : void RankInfoDetectClient::UpdateSelectedHostAddr(
     483              :     nlohmann::json& addrJson, const std::vector<IpAddress>& candidates, std::size_t selectedIndex) const
     484              : {
     485            9 :     const std::string oldAddr = addrJson[ADDR_FIELD].get<std::string>();
     486              :     // 只改写当前有效 addr,保留 backup_addr 原始配置,并随本地 RankTable 一并上报。
     487            9 :     addrJson[ADDR_FIELD] = candidates[selectedIndex].GetIpStr();
     488            9 :     HCCL_RUN_INFO(
     489              :         "[%s] select host addr success, devPhyId[%u], rankId[%u], "
     490              :         "selectedNicRole[%s], oldHostAddr[%s], selectedHostAddr[%s], candidateIndex[%zu], tryCount[%zu].",
     491              :         __func__, devPhyId_, rankId_, selectedIndex == 0 ? "primary" : "backup", oldAddr.c_str(),
     492              :         candidates[selectedIndex].Describe().c_str(), selectedIndex, selectedIndex + 1);
     493            9 : }
     494              : 
     495            1 : void RankInfoDetectClient::GetLocalDevInfoJson(const nlohmann::json& parseJson, nlohmann::json& localDevInfoJson)
     496              : {
     497            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     498              : 
     499              :     // rankList字段对应json内容
     500            1 :     nlohmann::json rankJsons;
     501            1 :     std::string msgRanklist = "error occurs when parser object of propName \"rank_list\"";
     502            1 :     TRY_CATCH_THROW(InvalidParamsException, msgRanklist, GetJsonPropertyList(parseJson, "rank_list", rankJsons););
     503              : 
     504              :     // 获取localrankJsons, 匹配deviceId字段与当前devPhyId_匹配的内容
     505            1 :     for (auto& rankJson : rankJsons) {
     506            1 :         u32 devId = 0;
     507            1 :         std::string msgDeviceId = "error occurs when parser object of propName \"device_id\"";
     508            1 :         TRY_CATCH_THROW(InvalidParamsException, msgDeviceId, devId = GetJsonPropertyUInt(rankJson, "device_id"););
     509            1 :         if (devId == devPhyId_) {
     510            1 :             HCCL_INFO("[RankInfoDetectClient::%s] find localDevInfoJson.", __func__);
     511            1 :             localDevInfoJson = rankJson;
     512            1 :             break;
     513              :         }
     514            1 :     }
     515              : 
     516            1 :     if (localDevInfoJson.empty()) {
     517            0 :         HCCL_ERROR("[%s] failed, no device_id matches devPhyId_[%u] in rank_list.", __func__, devPhyId_);
     518              :     }
     519              : 
     520              :     // 添加rankId
     521            1 :     localDevInfoJson["rank_id"] = rankId_;
     522              : 
     523            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     524            1 : }
     525              : 
     526            1 : void RankInfoDetectClient::GetLocalRankTableJson(const nlohmann::json& parseJson, nlohmann::json& localRankTableJson)
     527              : {
     528            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     529              : 
     530            1 :     std::string version;
     531            1 :     std::string msgVersion = "error occurs when parser object of propName \"version\"";
     532            1 :     TRY_CATCH_THROW(InvalidParamsException, msgVersion, version = GetJsonProperty(parseJson, "version"););
     533            1 :     localRankTableJson["version"] = version;
     534              : 
     535            1 :     std::string detour;
     536            1 :     std::string msgDetour = "error occurs when parser object of propName \"detour\"";
     537            1 :     TRY_CATCH_THROW(InvalidParamsException, msgDetour, detour = GetJsonProperty(parseJson, "detour", false););
     538            1 :     if (detour == "true") {
     539            0 :         localRankTableJson["detour"] = detour;
     540              :     }
     541              : 
     542            1 :     localRankTableJson["rank_count"] = rankSize_;
     543            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     544            1 : }
     545              : 
     546            1 : void RankInfoDetectClient::RecvRankTableMsg(vector<char>& rankInfoMsg)
     547              : {
     548            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     549              : 
     550              :     // 接收数据
     551            1 :     u64 revMsgLen = 0;
     552            1 :     std::unique_ptr<HostBuffer> msg = std::make_unique<HostBuffer>(MAX_BUFFER_LEN);
     553            1 :     char* msgAddr = reinterpret_cast<char*>(msg->GetAddr());
     554            1 :     CHK_PRT_THROW(
     555              :         !socketAgent_.RecvMsg(msgAddr, revMsgLen),
     556              :         HCCL_ERROR("RankInfoDetectClient::%s, recv rankTable error.", __func__), SocketException, "client recv fail");
     557              : 
     558              :     // 以vector<char>格式保存
     559            1 :     rankInfoMsg.resize(revMsgLen);
     560            1 :     rankInfoMsg.assign(msgAddr, msgAddr + revMsgLen);
     561              : 
     562            1 :     HCCL_INFO("[RankInfoDetectClient::%s] end, revMsgLen[%llu].", __func__, revMsgLen);
     563            1 : }
     564              : 
     565              : // 解析接收到的rank table信息
     566            2 : void RankInfoDetectClient::ParseRankTable(vector<char>& rankInfoMsg)
     567              : {
     568            2 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     569              : 
     570              :     // 消息格式: [ranktable大小(u32, 4字节)][ranktable数据(n字节)][step(4字节)][failedAgentIdList]
     571            2 :     BinaryStream binStream(rankInfoMsg);
     572              : 
     573              :     // 解析localRankInfo
     574            2 :     rankTable_ = RankTableInfo(binStream);
     575            2 :     rankTable_.Dump();
     576              : 
     577              :     // 解析step
     578              :     u32 receivedStep;
     579            2 :     binStream >> receivedStep;
     580              : 
     581              :     // 解析failedAgentIdList
     582            2 :     std::string failedAgentIdList;
     583            2 :     binStream >> failedAgentIdList;
     584            2 :     if (failedAgentIdList.size() > 0) {
     585              :         // 建链失败时,打印 root 节点发来的临终遗言
     586            7 :         RPT_INPUT_ERR(
     587              :             true, "EI0015", std::vector<std::string>({"error_reason"}),
     588              :             std::vector<std::string>({"rank connection failed, failedRankIdList: " + failedAgentIdList}));
     589            1 :         HCCL_ERROR(
     590              :             "[RankInfoDetectClient::%s] TopoDetect ERROR occur, failedRankIdList[%s]", __func__,
     591              :             failedAgentIdList.c_str());
     592              :     }
     593              : 
     594            2 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     595            3 : }
     596              : 
     597            1 : void RankInfoDetectClient::RecvRankTable()
     598              : {
     599              :     // 获取rankTable
     600            1 :     vector<char> rankInfoMsg{};
     601            1 :     RecvRankTableMsg(rankInfoMsg);
     602              : 
     603              :     // 解析rankTable
     604            1 :     ParseRankTable(rankInfoMsg);
     605              : 
     606              :     // 校验
     607            1 :     VerifyRankTable();
     608            1 : }
     609              : 
     610            1 : void RankInfoDetectClient::VerifyRankTable()
     611              : {
     612            1 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     613              : 
     614              :     // 校验rankCount符合预期
     615            1 :     if (rankTable_.rankCount != rankSize_) {
     616            0 :         THROW<InvalidParamsException>(StringFormat(
     617              :             "[RankInfoDetectClient::%s] rank_count[%u] does not match"
     618              :             " rankSize_[%u].",
     619              :             __func__, rankTable_.rankCount, rankSize_));
     620              :     }
     621              : 
     622              :     // 校验rankTable内容
     623            1 :     rankTable_.Check();
     624              :     // TLS开关一致性校验
     625            1 :     HcclResult ret = VerifyTlsConsistency();
     626            1 :     CHK_PRT_THROW(
     627              :         ret != HCCL_SUCCESS,
     628              :         HCCL_ERROR("[RankInfoDetectClient::%s] tls consistency verify failed, ret[%d]", __func__, ret),
     629              :         InvalidParamsException, "tls consistency verify failed");
     630              : 
     631            1 :     HcclResult hostDpuRet = VerifyHostDpuTlsConsistency();
     632            3 :     CHK_PRT_THROW(
     633              :         hostDpuRet != HCCL_SUCCESS,
     634              :         HCCL_ERROR("[RankInfoDetectClient::%s] hostDpuTls consistency verify failed, ret[%d]", __func__, hostDpuRet),
     635              :         InvalidParamsException, "hostDpuTls consistency verify failed");
     636              : 
     637            0 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     638            0 : }
     639              : 
     640            6 : HcclResult RankInfoDetectClient::GetLocalTlsStatus(TlsStatus& tlsStatus) const
     641              : {
     642            6 :     struct RaInfo raInfo {};
     643            6 :     raInfo.mode = NetworkMode::NETWORK_OFFLINE;
     644            6 :     raInfo.phyId = devPhyId_;
     645           12 :     return HrtRaGetTlsStatus(&raInfo, tlsStatus);
     646              : }
     647              : 
     648            8 : HcclResult RankInfoDetectClient::GetLocalHostDpuTlsStatus(TlsStatus& tlsStatus) const
     649              : {
     650            8 :     struct RaInfo raInfo {};
     651            8 :     raInfo.mode = NetworkMode::NETWORK_PEER_ONLINE;
     652            8 :     raInfo.phyId = devPhyId_;
     653           16 :     return HrtRaGetTlsStatus(&raInfo, tlsStatus);
     654              : }
     655              : 
     656           33 : void RankInfoDetectClient::GenerateTlsStatusStr(std::string& tlsStatusStr, const std::vector<u32>& tlsStatusRanks) const
     657              : {
     658           33 :     tlsStatusStr.clear();
     659           63 :     for (const auto& rank : tlsStatusRanks) {
     660           30 :         tlsStatusStr += std::to_string(rank) + ",";
     661              :     }
     662           33 :     if (!tlsStatusStr.empty() && tlsStatusStr.back() == ',') {
     663           23 :         tlsStatusStr.pop_back();
     664              :     }
     665           33 : }
     666              : 
     667            5 : void RankInfoDetectClient::ReportTlsConfigurationError(
     668              :     const std::string& tlsType, const std::string& tlsInconsistentTlsType, const std::string& tlsEnableRankStr,
     669              :     const std::string& tlsDisableRankStr, const std::string& tlsUnknownRankStr) const
     670              : {
     671              :     std::string expectMessage = "\"All ranks are consistent. Current status: rankList for enabled tls: "
     672           10 :                                 + tlsEnableRankStr + "; rankList for disabled tls: " + tlsDisableRankStr
     673            5 :                                 + "; rankList for query failure tls: " + tlsUnknownRankStr;
     674           10 :     std::string errormessage = "Value \"" + tlsInconsistentTlsType + "\" for config \"" + tlsType
     675            5 :                                + "\" is invalid. Expected: " + expectMessage;
     676              : 
     677           65 :     RPT_INPUT_ERR(
     678              :         true, "EI0016", std::vector<std::string>({"value", "variable", "expect"}),
     679              :         std::vector<std::string>({tlsInconsistentTlsType, "\"" + tlsType + "\"", expectMessage}));
     680              : 
     681            5 :     HCCL_ERROR("[ReportTlsConfigurationError][RanktableCheck] %s", errormessage.c_str());
     682           10 : }
     683              : 
     684            6 : HcclResult RankInfoDetectClient::VerifyTlsConsistency() const
     685              : {
     686           14 :     auto getTlsStatus = [](const NewRankInfo& rankInfo) {
     687           14 :         return rankInfo.tlsStatus;
     688              :     };
     689           18 :     return VerifyTlsConsistencyByTlsType("tls", getTlsStatus);
     690              : }
     691              : 
     692            7 : HcclResult RankInfoDetectClient::VerifyHostDpuTlsConsistency() const
     693              : {
     694           16 :     auto getTlsStatus = [](const NewRankInfo& rankInfo) {
     695           16 :         return rankInfo.hostDpuTlsStatus;
     696              :     };
     697           21 :     return VerifyTlsConsistencyByTlsType("hostDpuTls", getTlsStatus);
     698              : }
     699              : 
     700           13 : HcclResult RankInfoDetectClient::VerifyTlsConsistencyByTlsType(
     701              :     const std::string& tlsType, const std::function<TlsStatus(const NewRankInfo&)>& getTlsStatus) const
     702              : {
     703           13 :     bool isSupportCheckTlsStatus = true; // 用于标识是否存在不支持查询Tls开关状态的情况
     704           13 :     bool isTlsConsistent = true;         // 用于标识TLS开关状态是否一致
     705           13 :     std::vector<u32> tlsEnableRank;
     706           13 :     std::vector<u32> tlsDisableRank;
     707           13 :     std::vector<u32> tlsUnknownRank;
     708              : 
     709           43 :     for (const auto& rankInfo : rankTable_.ranks) {
     710           30 :         const TlsStatus tlsStatus = getTlsStatus(rankInfo);
     711           30 :         if (tlsStatus == TlsStatus::ENABLE) {
     712           11 :             tlsEnableRank.push_back(rankInfo.rankId);
     713           19 :         } else if (tlsStatus == TlsStatus::DISABLE) {
     714            9 :             tlsDisableRank.push_back(rankInfo.rankId);
     715              :         } else {
     716           10 :             isSupportCheckTlsStatus = false;
     717           10 :             tlsUnknownRank.push_back(rankInfo.rankId);
     718              :         }
     719              :     }
     720              : 
     721              :     // 将卡的信息汇总成string
     722           13 :     std::string tlsEnableRankStr;
     723           13 :     std::string tlsDisableRankStr;
     724           13 :     std::string tlsUnknownRankStr;
     725           13 :     GenerateTlsStatusStr(tlsEnableRankStr, tlsEnableRank);
     726           13 :     GenerateTlsStatusStr(tlsDisableRankStr, tlsDisableRank);
     727           13 :     if (!isSupportCheckTlsStatus) {
     728            7 :         GenerateTlsStatusStr(tlsUnknownRankStr, tlsUnknownRank);
     729              :     }
     730              : 
     731           13 :     std::string tlsInconsistentTlsType;
     732           13 :     if (!tlsEnableRank.empty() && !tlsDisableRank.empty()) {
     733            5 :         isTlsConsistent = false;
     734            5 :         tlsInconsistentTlsType = (tlsDisableRank.size() <= tlsEnableRank.size()) ? "Disable" : "Enable";
     735              :     }
     736              : 
     737              :     // 四种不同情况
     738           13 :     if (isTlsConsistent && isSupportCheckTlsStatus) {
     739              :         // 1.通信域所有卡都支持查询TLS开关状态,并且TLS开关状态都是一致的。
     740            4 :         HCCL_INFO("[Verify][%sConsistency] All ranks %sStatus are consistent", tlsType.c_str(), tlsType.c_str());
     741            9 :     } else if (!isTlsConsistent && isSupportCheckTlsStatus) {
     742              :         // 2.通信域所有卡都支持查询TLS开关状态,但是TLS开关状态存在不一致,报错。
     743            2 :         ReportTlsConfigurationError(
     744              :             tlsType, tlsInconsistentTlsType, tlsEnableRankStr, tlsDisableRankStr, tlsUnknownRankStr);
     745            2 :         return HCCL_E_PARA;
     746            7 :     } else if (isTlsConsistent && !isSupportCheckTlsStatus) {
     747              :         // 3.通信域内的部分卡不支持查询TLS开关状态,目前能查询到的卡的TLS开关状态是一致的,打印warning提醒
     748            4 :         HCCL_WARNING(
     749              :             "[Verify][%sConsistency] Some ranks do not support to check %sStatus, "
     750              :             "not support rankId: [%s]",
     751              :             tlsType.c_str(), tlsType.c_str(), tlsUnknownRankStr.c_str());
     752              :     } else {
     753              :         // 4.通信域内的部分卡不支持查询TLS开关状态,但是目前能查询到的卡的TLS开关状态已经不一致,报错
     754            3 :         ReportTlsConfigurationError(
     755              :             tlsType, tlsInconsistentTlsType, tlsEnableRankStr, tlsDisableRankStr, tlsUnknownRankStr);
     756            3 :         return HCCL_E_PARA;
     757              :     }
     758              : 
     759            8 :     return HCCL_SUCCESS;
     760           13 : }
     761              : 
     762            6 : void RankInfoDetectClient::HostListenPortDetect(NewRankInfo& rankInfo)
     763              : {
     764            6 :     std::string topoPath = GetRootInfoTopoFilePath();
     765            6 :     PhyTopoBuilder::GetInstance().Build(topoPath);
     766            6 :     auto devLogicId = HrtGetDevice();
     767            6 :     u32 devPhyId = rankInfo.deviceId;
     768           12 :     for (auto& rankLevelInfo : rankInfo.rankLevelInfos) {
     769              :         shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> graph
     770            7 :             = PhyTopo::GetInstance()->GetTopoGraph(rankLevelInfo.netLayer);
     771            7 :         if (graph == nullptr) {
     772            4 :             HCCL_DEBUG("[RankInfoDetectClient::%s]Can't find the layout %u Graph!", __func__, rankLevelInfo.netLayer);
     773            4 :             continue;
     774              :         }
     775            3 :         std::vector<std::shared_ptr<PhyTopo::Link>> links = graph->GetEdges(rankInfo.localId);
     776            5 :         for (auto& link : links) {
     777            3 :             if (link->GetSourceIFace()->GetPos() != AddrPosition::HOST) {
     778            1 :                 continue;
     779              :             }
     780            2 :             const std::set<LinkProtocol>& protocols = link->GetLinkProtocols();
     781            3 :             for (auto& protocol : protocols) {
     782            2 :                 LinkProtoType protoType = LinkProtocol2LinkProtoType(protocol);
     783            2 :                 if (protoType != LinkProtoType::RDMA || rankLevelInfo.rankAddrs.empty()) {
     784            1 :                     continue;
     785              :                 }
     786            1 :                 HCCL_DEBUG("[SocketManager::%s] find the host rdma link %s", __func__, link->Describe().c_str());
     787            1 :                 const IpAddress& hostIp = rankLevelInfo.rankAddrs[0].addr;
     788            1 :                 uint32_t hostPort = 0;
     789            1 :                 SetupHostListenPort(devLogicId, devPhyId, hostIp, hostPort);
     790            1 :                 rankInfo.hostPort = hostPort;
     791            1 :                 return;
     792              :             }
     793            2 :         }
     794            8 :     }
     795            6 : }
     796              : 
     797            2 : void RankInfoDetectClient::SetupHostListenPort(
     798              :     u32 devLogicId, u32 devPhyId, const IpAddress& hostIp, uint32_t& hostPort)
     799              : {
     800            2 :     std::lock_guard<std::mutex> lock(hostSocketLock_);
     801            2 :     u32 listenPort = HCCL_INVALID_PORT;
     802            2 :     auto portRange = EnvConfig::GetInstance().GetHostNicConfig().GetHostSocketPortRange();
     803            2 :     u32 basePort = EnvConfig::GetInstance().GetHostNicConfig().GetIfBasePort();
     804            2 :     if (portRange.empty() && basePort != HCCL_INVALID_PORT) {
     805            1 :         listenPort = basePort + devPhyId;
     806            1 :         HCCL_INFO("[RankInfoDetectClient::%s] BasePort is configured, listenPort[%u].", __func__, listenPort);
     807            1 :         hostPort = listenPort;
     808            1 :         return;
     809              :     }
     810              : 
     811            1 :     if (portRange.empty()) {
     812            1 :         constexpr u32 HOST_CONTROL_BASE_PORT = 60000; // 控制面起始port
     813            1 :         HCCL_INFO(
     814              :             "[RankInfoDetectClient::%s] No port configuration, using default port range[%u, %u]", __func__,
     815              :             HOST_CONTROL_BASE_PORT, HOST_CONTROL_BASE_PORT + HOST_CONTROL_PORT_COUNT);
     816            1 :         SocketPortRange defaultRange = {HOST_CONTROL_BASE_PORT, HOST_CONTROL_BASE_PORT + HOST_CONTROL_PORT_COUNT};
     817            1 :         portRange.push_back(defaultRange);
     818              :     }
     819              : 
     820            1 :     SocketHandle hostSocketHandle = HostSocketHandleManager::GetInstance().Create(devPhyId, hostIp);
     821            1 :     hostSocket_ = std::make_shared<Socket>(
     822            0 :         hostSocketHandle, hostIp, HCCL_INVALID_PORT, hostIp, "hostport_preempt", SocketRole::SERVER,
     823            1 :         NicType::HOST_NIC_TYPE);
     824            1 :     PreemptPortManager::GetInstance(devLogicId).ListenPreempt(hostSocket_, portRange, listenPort);
     825            1 :     HCCL_INFO("[RankInfoDetectClient::%s] preempt hostPort[%u] success.", __func__, listenPort);
     826              : 
     827              :     // 登记到进程级 map,供算子下发阶段复用,避免跨阶段端口竞争
     828            1 :     DevNetPortType portType(ConnectProtoType::RDMA);
     829            1 :     PortData portData(static_cast<RankId>(devPhyId), portType, 0, hostIp);
     830            1 :     SocketManager socketMgr(0, devPhyId, static_cast<u32>(devLogicId), "hostport_preempt");
     831            1 :     hostSocketRegistered_ = socketMgr.RegisterHostListenSocket(portData, hostSocket_);
     832              : 
     833            1 :     hostPort = listenPort;
     834            3 : }
     835              : 
     836           63 : void RankInfoDetectClient::SocketTearDown(u32 devPhyId)
     837              : {
     838           63 :     std::lock_guard<std::mutex> lock(hostSocketLock_);
     839           63 :     if (hostSocket_ == nullptr) {
     840           61 :         return;
     841              :     }
     842            2 :     const IpAddress& hostIp = hostSocket_->GetLocalIp();
     843            2 :     auto devLogicId = HrtGetDevice();
     844            2 :     if (hostSocketRegistered_) {
     845              :         // 已登记到 SocketManager::GetServerSocketMap(),所有权已转移给 map,
     846              :         // 由算子下发阶段 HostSocketStopListen refcount 归 0 时清理,此处跳过 Release/Destroy
     847            2 :         HCCL_INFO(
     848              :             "[RankInfoDetectClient::%s] hostSocket already registered to ServerSocketMap, "
     849              :             "skip Release/Destroy, only release local ref.",
     850              :             __func__);
     851            0 :     } else if (
     852            0 :         EnvConfig::GetInstance().GetHostNicConfig().GetHostSocketPortRange().size() > 0
     853            0 :         || EnvConfig::GetInstance().GetHostNicConfig().GetIfBasePort() == HCCL_INVALID_PORT) {
     854              :         // 若开启抢占监听端口
     855            0 :         PreemptPortManager::GetInstance(devLogicId).Release(hostSocket_);
     856            0 :         HostSocketHandleManager::GetInstance().Destroy(devPhyId, hostIp);
     857              :     }
     858            2 :     hostSocket_ = nullptr;
     859           63 : }
     860              : 
     861           59 : void RankInfoDetectClient::TearDown()
     862              : {
     863           59 :     HCCL_INFO("[RankInfoDetectClient::%s] start.", __func__);
     864           59 :     SocketTearDown(devPhyId_);
     865              : 
     866              :     // close socket
     867           59 :     clientSocket_->Close();
     868              : 
     869              :     // deinit handle
     870           59 :     HostSocketHandleManager::GetInstance().Destroy(devPhyId_, clientSocket_->GetLocalIp());
     871              : 
     872              :     // deinit ra in detach thread to avoid block main thread
     873           59 :     s32 deviceLogicId = HrtGetDevice();
     874           59 :     std::thread{[deviceLogicId]() {
     875           59 :         EXCEPTION_CATCH(
     876              :             HccpPeerManager::GetInstance().DeInit(deviceLogicId),
     877              :             HCCL_ERROR("[RankInfoDetectClient::TearDown] DeInit exception"));
     878          118 :     }}.detach();
     879              : 
     880           59 :     HCCL_INFO("[RankInfoDetectClient::%s] end.", __func__);
     881           59 : }
     882              : 
     883           60 : RankInfoDetectClient::~RankInfoDetectClient() { DECTOR_TRY_CATCH("RankInfoDetectClient", TearDown()); }
     884              : 
     885              : } // namespace Hccl
        

Generated by: LCOV version 2.0-1