LCOV - code coverage report
Current view: top level - legacy/ascend910/framework/common/src/topo - topoinfo_exchange_agent.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 38.5 % 649 250
Test Date: 2026-07-28 12:11:00 Functions: 34.0 % 47 16

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 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 "topoinfo_exchange_agent.h"
      12              : #include <iostream>
      13              : #include <sstream>
      14              : #include "externalinput_pub.h"
      15              : #include "adapter_error_manager_pub.h"
      16              : #include "config.h"
      17              : #include "sal_pub.h"
      18              : #include "device_capacity.h"
      19              : 
      20              : namespace hccl {
      21              : constexpr s32 DEVICE_LOGIC_ID_LENGTH = 4;
      22              : constexpr u32 AGENT_MAX_RETRY_TIME = 3;
      23              : 
      24           18 : TopoInfoExchangeAgent::TopoInfoExchangeAgent(HcclIpAddress &serverIp, u32 serverPort, std::string identifier,
      25           18 :     HcclNetDevCtx netDevCtx, HcclBasicRankInfo localRankInfo)
      26           18 :     : serverIP_(serverIp),
      27           18 :       serverPort_(serverPort),
      28           18 :       identifier_(identifier),
      29           18 :       localRankInfo_(localRankInfo),
      30           18 :       clusterTopoInfo_(),
      31           18 :       netDevCtx_(netDevCtx),
      32           36 :       isRetry_(GetExternalInputInterSuperPodRetryEnable())
      33           18 : {}
      34              : 
      35            0 : TopoInfoExchangeAgent::TopoInfoExchangeAgent(HcclIpAddress &serverIp, u32 serverPort, std::string identifier,
      36            0 :     HcclNetDevCtx netDevCtx, HcclBasicRankInfo localRankInfo, u32 connSize, u32 connRank)
      37            0 :     : serverIP_(serverIp),
      38            0 :       serverPort_(serverPort),
      39            0 :       identifier_(identifier),
      40            0 :       localRankInfo_(localRankInfo),
      41            0 :       clusterTopoInfo_(),
      42            0 :       netDevCtx_(netDevCtx),
      43            0 :       connSize_(connSize),
      44            0 :       connRank_(connRank),
      45            0 :       isRetry_(GetExternalInputInterSuperPodRetryEnable())
      46            0 : {}
      47              : 
      48            0 : TopoInfoExchangeAgent::TopoInfoExchangeAgent(HcclIpAddress &serverIp, u32 serverPort, std::string identifier,
      49            0 :     HcclNetDevCtx netDevCtx, HcclBasicRankInfo localRankInfo, HcclRankHandle rankInfo)
      50            0 :     : serverIP_(serverIp),
      51            0 :       serverPort_(serverPort),
      52            0 :       identifier_(identifier),
      53            0 :       localRankInfo_(localRankInfo),
      54            0 :       localRankHandle_(rankInfo),
      55            0 :       clusterTopoInfo_(),
      56            0 :       netDevCtx_(netDevCtx),
      57            0 :       isRetry_(GetExternalInputInterSuperPodRetryEnable())
      58            0 : {}
      59              : 
      60           18 : TopoInfoExchangeAgent::~TopoInfoExchangeAgent()
      61              : {
      62           18 :     Teardown();
      63           18 : }
      64              : 
      65            0 : HcclResult TopoInfoExchangeAgent::SetIsInterSuperPodRetryEnable(bool isInterSuperPodRetryEnable)
      66              : {
      67            0 :     isRetry_ = isInterSuperPodRetryEnable;
      68            0 :     return HCCL_SUCCESS;
      69              : }
      70              : 
      71            0 : HcclResult TopoInfoExchangeAgent::Setup()
      72              : {
      73            0 :     connSize_ = localRankInfo_.rankSize;
      74            0 :     connRank_ = localRankInfo_.rank;
      75              :     //填充要发送的localRankHandle的值
      76            0 :     localRankHandle_.rankId = localRankInfo_.rank;
      77            0 :     HcclResult ret = ConnectWithRetry(serverIP_, serverPort_, socket_);
      78            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[TopoInfoExchangeAgent][Setup]TopoExchangeAgent: "\
      79              :         "connect server[%s : %u] failed", serverIP_.GetReadableAddress(), serverPort_), ret);
      80            0 :     HCCL_INFO("TopoExchangeAgent: client connect with server ip[%s] port[%u] success.",
      81              :         serverIP_.GetReadableAddress(), serverPort_);
      82              : 
      83            0 :     if (!isByMasterInfo_ && localRankInfo_.rankSize > TOPO_HIERARCHICAL_ENABLE_THRESHOLD) {
      84            0 :         ret = socket_->Send(&localRankHandle_, sizeof(localRankHandle_));
      85            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
      86              :             HCCL_ERROR("[SendRankHandle]errNo[0x%016llx] rankID[%s] send localRankHandle to remote by"\
      87              :             "client fdHandle failed, ret[%u]", HCCL_ERROR_CODE(HCCL_E_TCP_TRANSFER), localRankInfo_.rank, ret), ret);
      88              :  
      89            0 :         CHK_RET(RecvGrpLeaderInfo(socket_, grpLeaderInfo_));
      90            0 :         u32 grpIndex = localRankInfo_.rank / TOPO_MAX_GROUP_SIZE;
      91            0 :         grpLeader_ = grpLeaderInfo_.GroupLeaderList[grpIndex];
      92            0 :     } else {
      93            0 :         CHK_RET(DetectClusterTopoInfo(socket_, clusterTopoInfo_)); 
      94            0 :         ret = VerifyClusterInfo(clusterTopoInfo_);
      95            0 :         if (ret != HCCL_SUCCESS) {
      96            0 :             auto current = g_broadcastStage.load(std::memory_order_acquire);
      97            0 :             if (current == BroadcastStage::Started) {
      98            0 :                 std::unique_lock<std::mutex> lock(g_broadcast_stage_mutex);
      99            0 :                 std::chrono::seconds timeout(MAX_WAIT_BROADCAST_SECONDS);
     100            0 :                 g_broadcast_stage_cv.wait_for(lock, timeout, [] {
     101            0 :                     return g_broadcastStage.load(std::memory_order_relaxed) == BroadcastStage::Completed;
     102              :                 });
     103            0 :             }
     104            0 :             HCCL_ERROR("[TopoInfoExchangeAgent][Setup]VerifyCluseterInfo failed, g_broadcastStage[%d]", g_broadcastStage.load());
     105              :         }
     106              : 
     107            0 :         return ret;
     108              :     }
     109              :  
     110            0 :     return HCCL_SUCCESS;
     111              : }
     112              : 
     113            0 : HcclResult TopoInfoExchangeAgent::SetupRank(std::shared_ptr<HcclSocket> socket)
     114              : {
     115            0 :     CHK_RET(RecvGrpLeaderInfo(socket, grpLeaderInfo_));
     116            0 :     u32 grpIndex = localRankInfo_.rank / TOPO_MAX_GROUP_SIZE;
     117            0 :     grpLeader_ = grpLeaderInfo_.GroupLeaderList[grpIndex];
     118            0 :     return HCCL_SUCCESS;
     119              : }
     120              : 
     121            0 : HcclResult TopoInfoExchangeAgent::SetupMember()
     122              : {
     123            0 :     HcclResult ret = Connect(serverIP_, serverPort_, socket_);
     124            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[TopoInfoExchangeAgent][Setup]SetupGroupMember: "\
     125              :         "connect server[%s : %u] failed", serverIP_.GetReadableAddress(), serverPort_), ret);
     126            0 :     HCCL_INFO("SetupGroupMember: client connect with server ip[%s] port[%u] success.",
     127              :         serverIP_.GetReadableAddress(), serverPort_);
     128              : 
     129            0 :     CHK_RET(DetectClusterTopoInfo(socket_, clusterTopoInfo_));
     130              : 
     131            0 :     CHK_RET(VerifyClusterInfo(clusterTopoInfo_));
     132              : 
     133            0 :     return HCCL_SUCCESS;
     134              : }
     135              : 
     136           18 : HcclResult TopoInfoExchangeAgent::Teardown()
     137              : {
     138           18 :     CHK_RET(Disconnect(socket_));
     139           18 :     return HCCL_SUCCESS;
     140              : }
     141              : 
     142            0 : HcclResult TopoInfoExchangeAgent::GetConnection(std::shared_ptr<HcclSocket> &socket)
     143              : {
     144            0 :     socket = socket_;
     145            0 :     return HCCL_SUCCESS;
     146              : }
     147              : 
     148            0 : HcclResult TopoInfoExchangeAgent::GetGroupLeader(HcclRankHandle &rankHandle)
     149              : {
     150            0 :     rankHandle = grpLeader_;
     151            0 :     return HCCL_SUCCESS;
     152              : }
     153              : 
     154            0 : HcclResult TopoInfoExchangeAgent::SetupByMasterInfo()
     155              : {
     156            0 :     isByMasterInfo_ = true;
     157            0 :     CHK_RET(Setup());
     158            0 :     return HCCL_SUCCESS;
     159              : }
     160              : 
     161            0 : HcclResult TopoInfoExchangeAgent::DetectClusterTopoInfo(
     162              :     std::shared_ptr<HcclSocket> socket, RankTable_t &clusterTopoInfo)
     163              : {
     164            0 :     RankTable_t localBasicInfo;
     165            0 :     CHK_RET(ConstructRankTableMsg(localBasicInfo));
     166            0 :     CHK_RET(SendClusterInfo(socket, localBasicInfo));
     167            0 :     HCCL_INFO("topo exchange client send rank basic info success.");
     168              : 
     169            0 :     CHK_RET(RecvClusterInfo(socket, clusterTopoInfo));
     170            0 :     HCCL_INFO("topo exchange client get rank basic info success.");
     171              : 
     172              :     // 按照rankId排序
     173            0 :     std::vector<RankInfo_t> &rankList = clusterTopoInfo_.rankList;
     174            0 :     sort(rankList.begin(), rankList.end(), [](const RankInfo_t &a, const RankInfo_t &b) {
     175            0 :         return a.rankId < b.rankId; });
     176              : 
     177            0 :     CHK_RET(SetServerIdx(clusterTopoInfo));
     178            0 :     CHK_RET(GroupSuperPodsByRankContinuity(clusterTopoInfo));
     179            0 :     CHK_RET(SetSuperPodIdx(clusterTopoInfo));
     180            0 :     return HCCL_SUCCESS;
     181            0 : }
     182              : 
     183            0 : HcclResult TopoInfoExchangeAgent::GroupSuperPodsByRankContinuity(RankTable_t &clusterInfo) const
     184              : {
     185              :     // 按照superPodId将节点分组,相同superPodId在一个组
     186              :     // clusterInfo已经按照rankId排好序,按顺序插入到新的subRankTable中,不需要再排序
     187            0 :     std::map<std::string, std::vector<RankInfo_t*>> podGroupClusters;
     188            0 :     for (auto& rankInfo : clusterInfo.rankList) {
     189            0 :         rankInfo.originalSuperPodId = rankInfo.superPodId; // 把用户配置的原始superPodId先保存下来
     190            0 :         podGroupClusters[rankInfo.superPodId].emplace_back(&rankInfo);
     191              :     }
     192            0 :     std::set<std::string> superPodIdSet;
     193            0 :     std::map<std::string, std::pair<u32, u32>> superPodIdRanges; // 记录每个逻辑超节点的rank id范围
     194            0 :     for (auto& subCluster : podGroupClusters) {
     195            0 :         auto& subClusterInfo = subCluster.second;
     196            0 :         if (subClusterInfo.size() <= 1) {
     197            0 :             continue;
     198              :         }
     199            0 :         u32 groupId = 0;
     200            0 :         superPodIdSet.insert(subCluster.first);
     201            0 :         RankInfo_t preRank = *(subClusterInfo[0]);
     202            0 :         superPodIdRanges[preRank.superPodId] = {preRank.rankId, preRank.rankId}; // 初始化范围
     203            0 :         for (u32 i = 1; i < subClusterInfo.size(); ++i) {
     204            0 :             RankInfo_t& curRank = *(subClusterInfo[i]);
     205              :             // 当前的curRank和上一个preRank的rankId不连续,分配新的逻辑超节点ID
     206            0 :             if (curRank.rankId != preRank.rankId + 1) {
     207            0 :                 std::string newSuperPodId = curRank.originalSuperPodId + "_HCCLSPLIT_" + std::to_string(groupId);
     208            0 :                 curRank.superPodId = newSuperPodId;
     209            0 :                 groupId++;
     210            0 :                 superPodIdRanges[curRank.superPodId] = {curRank.rankId, curRank.rankId}; // 初始化新的范围
     211            0 :             } else {
     212              :                 // 同一个sub通信域两个rank原始逻辑超节点是一致的
     213              :                 // rankId连续 上一个rank的superPodId可能已经重新分配,需要更新当前superPodId为上一个rank的
     214            0 :                 curRank.superPodId = preRank.superPodId;
     215            0 :                 superPodIdRanges[curRank.superPodId].second = curRank.rankId; // 更新最大rank id
     216              :             }
     217            0 :             superPodIdSet.insert(curRank.superPodId);
     218            0 :             preRank = curRank;
     219              :         }
     220            0 :     }
     221              :     // 打印每个逻辑超节点的rank id范围,只打印包含_HCCLSPLIT_的逻辑超节点
     222            0 :     for (const auto& entry : superPodIdRanges) {
     223            0 :         auto superPodId = entry.first;
     224            0 :         if (superPodId.find("_HCCLSPLIT_") != std::string::npos) {
     225            0 :             auto range = entry.second;
     226            0 :             HCCL_RUN_INFO("[TopoInfoExchangeAgent][%s]Split superPod, ID[%s], rank range[%u, %u]", __func__,
     227              :                 superPodId.c_str(), range.first, range.second);
     228              :         }
     229            0 :     }
     230            0 :     clusterInfo.superPodNum = superPodIdSet.size();
     231            0 :     return HCCL_SUCCESS; 
     232            0 : }
     233              : 
     234            0 : HcclResult TopoInfoExchangeAgent::SetServerIdx(RankTable_t &clusterInfo) const
     235              : {
     236              :     struct ServerSortInfo {
     237              :         u32 serverPosition;
     238              :         u32 selectedRankId;
     239              :     };
     240            0 :     std::vector<ServerSortInfo> serverSortInfoVec;
     241            0 :     for (u32 i = 0; i < clusterInfo.serverList.size(); i++) {
     242            0 :         for (u32 j = 0; j < clusterInfo.rankList.size(); j++) {
     243            0 :             if (clusterInfo.rankList[j].serverId == clusterInfo.serverList[i].serverId) {
     244              :                 // 每个server的rankid都是连续的,只需要取每个server里任意一个rankid进行排序
     245              :                 ServerSortInfo serverSortInfo;
     246            0 :                 serverSortInfo.serverPosition = i;
     247            0 :                 serverSortInfo.selectedRankId = clusterInfo.rankList[j].rankId;
     248            0 :                 serverSortInfoVec.push_back(serverSortInfo);
     249            0 :                 break;
     250              :             }
     251              :         }
     252              :     }
     253            0 :     sort(serverSortInfoVec.begin(), serverSortInfoVec.end(), [](const ServerSortInfo &a,
     254            0 :         const ServerSortInfo &b) { return a.selectedRankId < b.selectedRankId; });
     255              :     // 遍历ranklist,根据serverid获取serveridx
     256            0 :     for (u32 serverIdx = 0; serverIdx < serverSortInfoVec.size(); serverIdx++) {
     257            0 :         for (u32 j = 0; j < clusterInfo.rankList.size(); j++) {
     258            0 :             if (clusterInfo.rankList[j].serverId ==
     259            0 :                 clusterInfo.serverList[serverSortInfoVec[serverIdx].serverPosition].serverId) {
     260            0 :                 clusterInfo.rankList[j].serverIdx = serverIdx;
     261              :             }
     262              :         }
     263              :     }
     264            0 :     return HCCL_SUCCESS;
     265            0 : }
     266              : 
     267            1 : HcclResult TopoInfoExchangeAgent::SetSuperPodIdx(RankTable_t &clusterInfo) const
     268              : {
     269            1 :     std::map<std::string, u32> spodIdToIdx;
     270            1 :     bool isDiffDeviceType = false;
     271            1 :     DevType standardDevType = DevType::DEV_TYPE_NOSOC;
     272            1 :     if (clusterInfo.rankList.size() > 0) {
     273            1 :         standardDevType = clusterInfo.rankList[0].deviceInfo.deviceType;
     274              :     }
     275            4 :     for (u32 i = 0; i < clusterInfo.rankList.size(); ++i) {
     276            3 :         RankInfo_t& rankInfo = clusterInfo.rankList[i];
     277            3 :         if (rankInfo.deviceInfo.deviceType != standardDevType) {
     278            0 :             isDiffDeviceType = true;
     279              :         }
     280              : 
     281            3 :         if (isDiffDeviceType) {
     282            0 :             rankInfo.superPodIdx = spodIdToIdx.size(); 
     283            3 :         } else if (spodIdToIdx.find(rankInfo.superPodId) == spodIdToIdx.end()) {
     284            2 :             rankInfo.superPodIdx = spodIdToIdx.size();
     285            2 :             spodIdToIdx.insert({rankInfo.superPodId, rankInfo.superPodIdx});
     286            1 :         } else if (spodIdToIdx[rankInfo.superPodId] + 1 == spodIdToIdx.size()) {
     287            0 :             rankInfo.superPodIdx = spodIdToIdx[rankInfo.superPodId];
     288              :         } else {
     289            1 :             u32 preIndex = (i > 0) ? i - 1 : i;
     290            1 :             RankInfo_t& preRankInfo = clusterInfo.rankList[preIndex];
     291            1 :             u32 index = 0;
     292            1 :             for (; index < preIndex; index++) {
     293            1 :                 RankInfo_t& tmpRankInfo = clusterInfo.rankList[index];
     294            1 :                 if(tmpRankInfo.superPodId == rankInfo.superPodId) {
     295            1 :                     break;
     296              :                 }
     297              :             }
     298              :             // 超节点内rank id不连续
     299            1 :             HCCL_RUN_WARNING("rank in superPodId is not continuous, pre: rank[%u] superPodId[%s], "\
     300              :                 "cur: rank[%u] superPodId[%s], ", preRankInfo.rankId, preRankInfo.superPodId.c_str(),
     301              :                 rankInfo.rankId, rankInfo.superPodId.c_str());
     302            1 :             rankInfo.superPodIdx = spodIdToIdx[rankInfo.superPodId];
     303              :         }
     304            3 :         HCCL_INFO("SetSuperPodIdx rankList[%u]: rankId[%u], superPodId[%s], superPodIdx[%u], sdid[%u]",
     305              :             i, rankInfo.rankId, rankInfo.superPodId.c_str(), rankInfo.superPodIdx, rankInfo.superDeviceId);
     306              :     }
     307            1 :     return HCCL_SUCCESS;
     308            1 : }
     309              : 
     310            0 : HcclResult TopoInfoExchangeAgent::GetClusterTopoInfo(RankTable_t &clusterInfo)
     311              : {
     312            0 :     clusterInfo.nicDeploy = clusterTopoInfo_.nicDeploy;
     313            0 :     clusterInfo.deviceNum = clusterTopoInfo_.deviceNum;
     314            0 :     clusterInfo.serverNum = clusterTopoInfo_.serverNum;
     315            0 :     clusterInfo.superPodNum = clusterTopoInfo_.superPodNum;
     316            0 :     clusterInfo.rankNum = clusterTopoInfo_.rankNum;
     317            0 :     clusterInfo.rankList = clusterTopoInfo_.rankList;
     318            0 :     clusterInfo.serverList = clusterTopoInfo_.serverList;
     319              : 
     320            0 :     return HCCL_SUCCESS;
     321              : }
     322            0 : HcclResult TopoInfoExchangeAgent::GetIdentifier(u32 &identify)
     323              : {
     324            0 :     identify = identifierNum_;
     325            0 :     return HCCL_SUCCESS;
     326              : }
     327            0 : HcclResult TopoInfoExchangeAgent::Connect(HcclIpAddress &serverIp, u32 port,
     328              :     std::shared_ptr<HcclSocket> &socket)
     329              : {
     330            0 :     std::string tag = TOPO_DETECT_TAG + "_" + identifier_ + "_" + std::to_string(port);
     331            0 :     EXCEPTION_CATCH((socket = std::make_shared<HcclSocket>(tag,
     332              :         netDevCtx_, serverIp, port, HcclSocketRole::SOCKET_ROLE_CLIENT)), return HCCL_E_PTR);
     333            0 :     CHK_SMART_PTR_NULL(socket);
     334            0 :     CHK_RET(socket->Init());
     335            0 :     CHK_RET(socket->Connect());
     336              : 
     337            0 :     return GetConnection(serverIp, port, socket);
     338            0 : }
     339              : 
     340            0 : HcclResult TopoInfoExchangeAgent::ConnectWithRetry(HcclIpAddress &serverIp, u32 port,
     341              :     std::shared_ptr<HcclSocket> &socket)
     342              : {
     343            0 :     u32 retryTime = 1;
     344            0 :     HcclResult ret = HCCL_SUCCESS;
     345            0 :     while (retryTime <= AGENT_MAX_RETRY_TIME) {
     346            0 :         std::string tag = TOPO_DETECT_TAG + "_" + identifier_ + "_" + std::to_string(port);
     347            0 :         EXCEPTION_CATCH((socket = std::make_shared<HcclSocket>(tag,
     348              :             netDevCtx_, serverIp, port, HcclSocketRole::SOCKET_ROLE_CLIENT)), return HCCL_E_PTR);
     349            0 :         CHK_SMART_PTR_NULL(socket);
     350            0 :         CHK_RET(socket->Init());
     351            0 :         CHK_RET(socket->Connect());
     352              :  
     353            0 :         CHK_RET(GetConnection(serverIp, port, socket));
     354              : 
     355            0 :         ret = TryRecvFromServer(socket, retryTime);
     356            0 :         if (ret == HCCL_SUCCESS) {
     357            0 :             break;
     358              :         } else {
     359            0 :             retryTime++;
     360              :         }
     361            0 :     }
     362            0 :     return ret;
     363              : }
     364              : 
     365            0 : HcclResult TopoInfoExchangeAgent::TryRecvFromServer(std::shared_ptr<HcclSocket> &socket, u32 retryTime)
     366              : {
     367              :     // client端获取socket之后尝试从server接收数据,若在一定时间内没有接收到,则重新发起建链请求
     368            0 :     u32 timeout = GetExternalInputHcclLinkTimeOut() / AGENT_MAX_RETRY_TIME;
     369            0 :     char recvMsgBuf[sizeof(TOPO_EXCHANGE_CHECK_MESSAGE)] = {0};
     370            0 :     auto ret = HCCL_SUCCESS;
     371            0 :     if (retryTime == AGENT_MAX_RETRY_TIME) {
     372            0 :         ret = socket->Recv(recvMsgBuf, sizeof(TOPO_EXCHANGE_CHECK_MESSAGE), timeout);
     373              :     } else {
     374              :         // 重试时打印RUN_WARN日志
     375            0 :         SetErrToWarnSwitch(true);
     376            0 :         ret = socket->Recv(recvMsgBuf, sizeof(TOPO_EXCHANGE_CHECK_MESSAGE), timeout);
     377            0 :         SetErrToWarnSwitch(false);
     378              :     }
     379              :     
     380            0 :     if (ret == HCCL_SUCCESS) {
     381            0 :         HCCL_RUN_INFO("[%s]recvMes %s", __func__, recvMsgBuf);
     382            0 :     } else if (retryTime < AGENT_MAX_RETRY_TIME) {
     383            0 :         HCCL_RUN_WARNING("[%s]client recv from server failed, will try to connect with server again.", __func__);
     384              :     } else {
     385            0 :         HCCL_ERROR("[%s]failed to recv messages from server with %u times", __func__, AGENT_MAX_RETRY_TIME);
     386              :     }
     387              : 
     388            0 :     return ret;
     389              : }
     390              : 
     391            0 : void TopoInfoExchangeAgent::PrintSocketTimeoutReasons(HcclIpAddress &serverIp, u32 port,
     392              :     std::shared_ptr<HcclSocket> &socket)
     393              : {
     394            0 :     HCCL_ERROR("current rank connect to server timeout, maybe due to following reasons:");
     395            0 :     HCCL_ERROR("1. local host ip is [%s], server host ip and port is [%s:%u], Please check the network connectivity. "
     396              :         "If it is not connected, modify the network configuration or use HCCL_SOCKET_IFNAME and HCCL_IF_BASE_PORT to specify ifname and server port.",
     397              :         socket->GetLocalIp().GetReadableIP(), serverIp.GetReadableIP(), port);
     398            0 :     HCCL_ERROR("2. Check whether any other exceptions have occurred on server[%s] or "
     399              :         "whether the time difference between the execution of hcom on ranks exceeds the timeout threshold.",
     400              :         serverIp.GetReadableIP());
     401            0 : }
     402              : 
     403            0 : HcclResult TopoInfoExchangeAgent::GetConnection(HcclIpAddress &serverIp, u32 port,
     404              :     std::shared_ptr<HcclSocket> &socket)
     405              : {
     406            0 :     auto startTime = std::chrono::steady_clock::now();
     407            0 :     auto timeout = std::chrono::seconds(GetExternalInputHcclLinkTimeOut());
     408              :     while (true) {
     409            0 :         std::string errormessage = "1. The current node " + std::string(serverIp.GetReadableIP()) +
     410            0 :                                    " is disconnected from the host of the root node " + std::string(localRankHandle_.ip) + ". "\
     411            0 :                                    "2. the timeout set by the HCCL_CONNECT_TIMEOUT environment variable is too short";
     412            0 :         if ((std::chrono::steady_clock::now() - startTime) >= timeout) {
     413            0 :             RPT_INPUT_ERR(true, "EI0015", std::vector<std::string>({"error_reason"}), \
     414              :                 std::vector<std::string>({errormessage}));
     415            0 :             HCCL_ERROR("[%s][%s] topo exchange agent get socket timeout! timeout[%lld s]",
     416              :                 LOG_KEYWORDS_INIT_GROUP.c_str(), LOG_KEYWORDS_RANKTABLE_DETECT.c_str(), timeout);
     417            0 :             PrintSocketTimeoutReasons(serverIp, port, socket);
     418            0 :             sleep(WAIT_ERROR_BROADCAST_TIME);
     419            0 :             return HCCL_E_TIMEOUT;
     420              :         }
     421            0 :         HcclSocketStatus status = socket->GetStatus();
     422            0 :         if (status == HcclSocketStatus::SOCKET_CONNECTING) {
     423            0 :             SaluSleep(ONE_MILLISECOND_OF_USLEEP);
     424            0 :         } else if (status != HcclSocketStatus::SOCKET_OK) {
     425            0 :             HCCL_ERROR("[Get][Connection]server: get socket failed ret[%d]", status);
     426            0 :             return HCCL_E_TCP_CONNECT;
     427              :         } else {
     428            0 :             HCCL_INFO("TopoInfoExchangeAgent get socket success.");
     429            0 :             std::string agentID;
     430            0 :             if (isByMasterInfo_) {
     431            0 :                 agentID = localRankInfo_.superPodId + "/";
     432            0 :                 GenerateAgentID(localRankInfo_, agentID);
     433              :             } else {
     434            0 :                 std::string rankID = std::to_string(connRank_);
     435            0 :                 agentID = std::string(16 - rankID.length(), '0') + rankID;  // agent id为rank id,16位,左对齐补零
     436            0 :             }
     437            0 :             char agentBuf[MAX_AGENT_BUF_SIZE] = {0};
     438            0 :             s32 sRet = memcpy_s(agentBuf, sizeof(agentBuf), agentID.c_str(), agentID.size());
     439            0 :             CHK_PRT_RET(sRet != EOK, HCCL_ERROR("memcpy_s failed, errorno[%d]", sRet), HCCL_E_MEMORY);
     440            0 :             HcclResult ret = socket->Send(&agentBuf, sizeof(agentBuf));
     441            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     442              :                 HCCL_ERROR("[Get][Connection]errNo[0x%016llx] agentID[%s] send local rank id to remote "\
     443              :                     "by client fdHandle failed, ret[%u]", HCCL_ERROR_CODE(HCCL_E_TCP_TRANSFER), agentBuf, ret), ret);
     444            0 :             ret = socket->Send(&connSize_, sizeof(connSize_));
     445            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     446              :                 HCCL_ERROR("[Get][Connection]errNo[0x%016llx] rank[%u] send local rank num[%u] to "\
     447              :                     "remote by client fdHandle failed, ret[%u]", HCCL_ERROR_CODE(HCCL_E_TCP_TRANSFER),
     448              :                     localRankInfo_.rank, localRankInfo_.rankSize, ret), ret);
     449            0 :             HCCL_INFO("local rank[%u] get socket connection with server[%s] port[%u] success.",
     450              :                 localRankInfo_.rank, serverIp.GetReadableAddress(), port);
     451            0 :             break;
     452            0 :         }
     453            0 :     }
     454            0 :     return HCCL_SUCCESS;
     455            0 : }
     456              : 
     457            0 : std::string TopoInfoExchangeAgent::Dec2Hex(s32 i, u32 width)
     458              : {
     459            0 :     std::string temp;
     460            0 :     std::stringstream ss;
     461            0 :     ss << std::hex << i;
     462            0 :     ss >> temp;
     463            0 :     if (width > temp.size()) {
     464            0 :         return std::string((width - temp.size()), '0') + temp;
     465              :     } else {
     466            0 :         HCCL_WARNING("Dec2Hex: length[%u] is over width[%u]", temp.size(), width);
     467              :     }
     468            0 :     return temp;
     469            0 : }
     470              : 
     471            0 : void TopoInfoExchangeAgent::GenerateAgentID(HcclBasicRankInfo &localRankInfo, std::string &agentID)
     472              : {
     473            0 :     struct in_addr addr = localRankInfo.hostIP.GetBinaryAddress().addr;
     474            0 :     struct in6_addr addr6 = localRankInfo.hostIP.GetBinaryAddress().addr6;
     475            0 :     if (localRankInfo.hostIP.IsIPv6()) {
     476            0 :         for (size_t i = 0; i < sizeof(addr6.s6_addr); i++) {
     477            0 :             agentID += Dec2Hex(addr6.s6_addr[i], 2); // 转换为2位十六进制数据,左对齐补零
     478              :         }
     479              :     } else {
     480            0 :         for (size_t i = 0; i < sizeof(addr.s_addr) / sizeof(u8); i++) {
     481            0 :             agentID += Dec2Hex(*(reinterpret_cast<u8 *>(&addr.s_addr) + i), 2); // 转换为2位十六进制数据,左对齐补零
     482              :         }
     483              :     }
     484            0 :     agentID.append("/");
     485            0 :     std::string devID = std::to_string(localRankInfo.deviceLogicID);
     486            0 :     CHK_PRT_RET(devID.size() > DEVICE_LOGIC_ID_LENGTH, HCCL_ERROR("deviceLogicID[%s] is invalid", devID.c_str()),);
     487              :     // device id转换为4位十进制数字,左对齐补零
     488            0 :     agentID.append(std::string((DEVICE_LOGIC_ID_LENGTH - devID.size()), '0') + devID);
     489            0 :     HCCL_INFO("GenerateAgentID agentID[%s]", agentID.c_str());
     490            0 :     return;
     491            0 : }
     492              : 
     493           18 : HcclResult TopoInfoExchangeAgent::Disconnect(std::shared_ptr<HcclSocket> &socket)
     494              : {
     495           18 :     CHK_RET(DisconnectSocket(socket));
     496           18 :     socket = nullptr;
     497              : 
     498           18 :     return HCCL_SUCCESS;
     499              : }
     500              : 
     501            0 : HcclResult TopoInfoExchangeAgent::RecvGrpLeaderInfo(std::shared_ptr<HcclSocket> socket, GroupLeader_t &leaderInfo)
     502              : {   
     503              :     //每次获取之前先清空 保证填充之后的数据是最新的
     504            0 :     leaderInfo.grpLeaderNum = 0;
     505            0 :     leaderInfo.GroupLeaderList.clear();
     506            0 :     CHK_RET(RecvGrpLeaderInfoMsg(socket, leaderInfo));
     507            0 :     return HCCL_SUCCESS;
     508              : }
     509              : 
     510            0 : HcclResult TopoInfoExchangeAgent::SendGroupLeaderPortInfo(std::shared_ptr<HcclSocket> socket,  HcclRankHandle &rankHandle) 
     511              : {   
     512            0 :     CHK_RET(GetConnection(socket));
     513            0 :     HcclResult ret = socket->Send(&rankHandle, sizeof(rankHandle));
     514            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[TopoInfoExchangeAgent][SendGroupLeaderPortInfo]errNo[0x%016llx] " \
     515              :         "send grpleader port info fail", HCCL_ERROR_CODE(ret)), ret);
     516            0 :     return HCCL_SUCCESS;
     517              : }
     518              : 
     519            0 : HcclResult TopoInfoExchangeAgent::ConstructRankTableMsg(RankTable_t &clusterInfo)
     520              : {
     521            0 :     RankInfo_t myRankInfo;
     522            0 :     myRankInfo.rankId = localRankInfo_.rank;
     523            0 :     myRankInfo.hostIp = localRankInfo_.hostIP;
     524            0 :     myRankInfo.hostPort = localRankInfo_.hostPort;
     525            0 :     myRankInfo.deviceInfo.devicePhyId = localRankInfo_.devicePhysicID;
     526            0 :     myRankInfo.deviceInfo.deviceIp = localRankInfo_.deviceIP;
     527            0 :     myRankInfo.deviceInfo.deviceType = localRankInfo_.deviceType;
     528            0 :     myRankInfo.deviceInfo.backupDeviceIp = localRankInfo_.backupDeviceIP;
     529            0 :     myRankInfo.deviceInfo.port = localRankInfo_.deviceNicPort;
     530            0 :     myRankInfo.deviceInfo.vnicPort = localRankInfo_.deviceVnicPort;
     531            0 :     myRankInfo.deviceInfo.backupPort = localRankInfo_.backupDevicePort;
     532            0 :     myRankInfo.superPodId = localRankInfo_.superPodId;
     533            0 :     myRankInfo.superDeviceId = localRankInfo_.superDeviceId;
     534            0 :     myRankInfo.tlsStatus = localRankInfo_.tlsStatus;
     535            0 :     ConstructRankTableServerId(myRankInfo.serverId);
     536              : 
     537            0 :     ServerInfo_t myServerInfo;
     538            0 :     myServerInfo.serverId = myRankInfo.serverId;
     539              : 
     540            0 :     clusterInfo.nicDeploy = localRankInfo_.nicDeploy;
     541            0 :     clusterInfo.rankList.push_back(myRankInfo);
     542            0 :     clusterInfo.serverList.push_back(myServerInfo);
     543            0 :     return HCCL_SUCCESS;
     544            0 : }
     545              : 
     546            0 : void TopoInfoExchangeAgent::ConstructRankTableServerId(std::string &serverId)
     547              : {
     548            0 :     serverId = localRankInfo_.hostIP.GetReadableIP();
     549              :     // 配置逻辑超节点时, serverId要根据逻辑超节点划分
     550            0 :     if (localRankInfo_.deviceType == DevType::DEV_TYPE_910_93 && GetExternalInputLogicSuperPodId().empty() == false) {
     551            0 :         serverId += "_" + GetExternalInputLogicSuperPodId();
     552              :     }
     553            0 :     HCCL_INFO("ConstructRankTableServerId serverId %s", serverId.c_str());
     554            0 : }
     555              : 
     556            0 : HcclResult TopoInfoExchangeAgent::SetTransportInfo(RankTable_t &clusterInfo)
     557              : {
     558            0 :     CHK_PRT_RET(clusterInfo.rankList.size() <= localRankInfo_.rank, HCCL_ERROR("[Set][TransportInfo]rank list is "\
     559              :         "invalid. size[%zu] should be greater than myRank[%u].", clusterInfo.rankList.size(), localRankInfo_.rank),
     560              :         HCCL_E_INTERNAL);
     561            0 :     RankInfo_t& myRankInfo = clusterInfo.rankList[localRankInfo_.rank];
     562            0 :     TransportInfo_t transportInfo = {0};
     563              : 
     564            0 :     for (u32 index = 0; index < clusterInfo.rankList.size(); index++) {
     565            0 :         transportInfo.dstRankId = clusterInfo.rankList[index].rankId;
     566            0 :         HcclResult ret = DetectTransportType(myRankInfo, clusterInfo.rankList[index], transportInfo.transportType);
     567            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
     568              :             HCCL_ERROR("[Set][TransportInfo]rank[%u] detect transport type failed, ret[%u]. "\
     569              :                 "remote[%u]", localRankInfo_.rank, ret, transportInfo.dstRankId), ret);
     570            0 :         myRankInfo.transportInfo.push_back(transportInfo);
     571              :     }
     572            0 :     return HCCL_SUCCESS;
     573              : }
     574              : 
     575            0 : HcclResult TopoInfoExchangeAgent::DetectTransportType(const RankInfo_t& localRankInfo,
     576              :     const RankInfo_t& remoteRankInfo, TransportType& transportType) const
     577              : {
     578            0 :     if (remoteRankInfo.serverId == localRankInfo.serverId) {
     579            0 :             transportType = TransportType::TRANS_TYPE_P2P;
     580              :     }
     581            0 :     return HCCL_SUCCESS;
     582              : }
     583              : 
     584            4 : HcclResult TopoInfoExchangeAgent::VerifyClusterInfo(RankTable_t &clusterInfo)
     585              : {
     586            4 :     std::string errormessage;
     587              : 
     588            4 :     if (clusterInfo.rankList.size() != localRankInfo_.rankSize) {
     589            2 :         errormessage = "The number of ranks[" + std::to_string(localRankInfo_.rankSize) +
     590            4 :                                "]passed by the communicator initialization interface does not match the number of ranks[" + std::to_string(clusterInfo.rankList.size()) +
     591            1 :                                "]obtained during cluster information negotiction.";
     592            1 :         HCCL_ERROR("[%s][%s]%s",
     593              :             LOG_KEYWORDS_INIT_GROUP.c_str(),
     594              :             LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     595              :             errormessage.c_str());
     596            1 :         return HCCL_E_PARA;
     597              :     }
     598              : 
     599            3 :     if (clusterInfo.rankNum != localRankInfo_.rankSize) {
     600            2 :         errormessage = "The number of ranks[" + std::to_string(localRankInfo_.rankSize) +
     601            4 :                             "]passed by the communicator initialization interface does not match the number of ranks[" + std::to_string(clusterInfo.rankNum) +
     602            1 :                             "] obtained during cluster information negotiction.";
     603            1 :         HCCL_ERROR("[%s][%s]%s",
     604              :             LOG_KEYWORDS_INIT_GROUP.c_str(),
     605              :             LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     606              :             errormessage.c_str());
     607            1 :         return HCCL_E_PARA;
     608              :     }
     609              : 
     610            2 :     if (clusterInfo.serverNum != clusterInfo.serverList.size()) {
     611            4 :         errormessage = "server num[" + std::to_string(clusterInfo.serverNum) + "] is different with server list size[" +
     612            6 :                        std::to_string(clusterInfo.serverList.size()) + "] in total topo rank info";
     613           14 :         RPT_INPUT_ERR(true, "EI0015",
     614              :             std::vector<std::string>({ "error_reason"}),
     615              :             std::vector<std::string>({ errormessage }));
     616            2 :         HCCL_ERROR("[%s][%s]%s",
     617              :             LOG_KEYWORDS_INIT_GROUP.c_str(),
     618              :             LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     619              :             errormessage.c_str());
     620            2 :         return HCCL_E_PARA;
     621              :     }
     622              : 
     623            0 :     if (clusterInfo.nicDeploy != localRankInfo_.nicDeploy) {
     624            0 :         errormessage = "nicDeploy[" + std::to_string(static_cast<int>(localRankInfo_.nicDeploy)) +
     625            0 :                         "] is different with nicDeploy[" + std::to_string(static_cast<int>(clusterInfo.nicDeploy)) + "] in total topo rank info";
     626            0 :         RPT_INPUT_ERR(true, "EI0015",
     627              :             std::vector<std::string>({ "error_reason"}),
     628              :             std::vector<std::string>({ errormessage }));
     629            0 :         HCCL_ERROR("[%s][%s]%s",
     630              :             LOG_KEYWORDS_INIT_GROUP.c_str(),
     631              :             LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     632              :             errormessage.c_str());
     633            0 :         return HCCL_E_PARA;
     634              :     }
     635              : 
     636            0 :     CHK_RET(VerifyClusterRankID(clusterInfo));
     637            0 :     if (localRankInfo_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE) {
     638            0 :         CHK_RET(VerifyClusterDeviceIP(clusterInfo));
     639            0 :         CHK_RET(VerifyClusterBackupDeviceIP(clusterInfo));
     640              :     }
     641            0 :     std::map<std::string, std::vector<RankInfo_t>> serverMap;
     642            0 :     for (uint32_t i = 0; i < clusterInfo.rankList.size(); i++) {
     643            0 :         auto iter = serverMap.find(clusterInfo.rankList[i].serverId);
     644            0 :         if (iter == serverMap.end()) {
     645            0 :             std::vector<RankInfo_t> vec;
     646            0 :             vec.push_back(clusterInfo.rankList[i]);
     647            0 :             serverMap.insert({clusterInfo.rankList[i].serverId, vec});
     648            0 :         } else {
     649            0 :             serverMap[clusterInfo.rankList[i].serverId].push_back(clusterInfo.rankList[i]);
     650              :         }
     651              :     }
     652              : 
     653            0 :     if (clusterInfo.serverNum != serverMap.size()) {
     654            0 :         errormessage = "server num[" + std::to_string(clusterInfo.serverNum) +
     655            0 :                         "] is different with server num[" +
     656            0 :                         std::to_string(serverMap.size()) + "] in total topo rank info";
     657            0 :         RPT_INPUT_ERR(true,
     658              :             "EI0015",
     659              :             std::vector<std::string>({"error_reason"}),
     660              :             std::vector<std::string>({ errormessage }));
     661            0 :         HCCL_ERROR("[%s][%s]%s",
     662              :             LOG_KEYWORDS_INIT_GROUP.c_str(),
     663              :             LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     664              :             errormessage.c_str());
     665            0 :         return HCCL_E_PARA;
     666              :     }
     667              : 
     668            0 :     uint32_t deviceNumInServer = 0;
     669            0 :     for (auto &server : serverMap) {
     670            0 :         CHK_PRT_RET((server.second.size() == 0),
     671              :             HCCL_ERROR("[%s][%s]server ip[%s] has %u device.",
     672              :                 LOG_KEYWORDS_INIT_GROUP.c_str(),
     673              :                 LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     674              :                 server.first.c_str(),
     675              :                 server.second.size()),
     676              :             HCCL_E_PARA);
     677              : 
     678            0 :         if (deviceNumInServer != 0) {
     679            0 :             HCCL_WARNING("[%s][%s]server ip[%s] has %u devices, other server has %u.",
     680              :                 LOG_KEYWORDS_INIT_GROUP.c_str(),
     681              :                 LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     682              :                 server.first.c_str(),
     683              :                 server.second.size(),
     684              :                 deviceNumInServer);
     685              :         }
     686            0 :         deviceNumInServer = server.second.size();
     687            0 :         HcclResult ret = VerifyServerDevicePhysicID(server.second);
     688            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
     689              :             HCCL_ERROR("[%s][%s]server id[%s] verify device physic id failed.",
     690              :                 LOG_KEYWORDS_INIT_GROUP.c_str(),
     691              :                 LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     692              :                 server.first.c_str()),
     693              :             HCCL_E_PARA);
     694              :     }
     695              : 
     696            0 :     bool useSuperPodMode = false;
     697            0 :     CHK_RET(IsSuperPodMode(useSuperPodMode));
     698            0 :     bool isSinglePodInterHccs = clusterInfo.superPodNum == 1 && GetExternalInputInterHccsDisable() == false && useSuperPodMode;
     699              :     // 单超节点,并且节点间走HCCS场景,不校验ip family
     700            0 :     if (clusterInfo.serverNum > 1 && !isSinglePodInterHccs) {
     701            0 :         CHK_RET(CheckRankIpFamily(clusterInfo.rankList));
     702              :     }
     703              : 
     704              :     // 超节点校验
     705            0 :     CHK_RET(VerifyClusterSuperPodInfo(clusterInfo.rankList));
     706              : 
     707              :     // TLS开关一致性校验
     708            0 :     CHK_RET(VerifyClusterTlsConsistency(clusterInfo));
     709            0 :     return HCCL_SUCCESS;
     710            6 : }
     711              : 
     712            1 : HcclResult TopoInfoExchangeAgent::VerifyClusterDeviceIP(const RankTable_t &clusterInfo)
     713              : {
     714            1 :     if (clusterInfo.rankList.size() == 1) {
     715            0 :         return HCCL_SUCCESS;
     716              :     }
     717            1 :     if (clusterInfo.serverList.size() == 1) {
     718              :         // 单机场景对 device ip不做要求
     719            0 :         return HCCL_SUCCESS;
     720              :     }
     721            1 :     bool useSuperPodMode = false;
     722            1 :     CHK_RET(IsSuperPodMode(useSuperPodMode));
     723            1 :     if (clusterInfo.superPodNum == 1 && GetExternalInputInterHccsDisable() == false && useSuperPodMode) {
     724              :         // 单超节点,并且节点间走HCCS场景,device ip不做要求
     725            0 :         return HCCL_SUCCESS;
     726              :     }
     727            1 :     for (u32 i = 0; i < (clusterInfo.rankList.size() - 1); i++) {
     728            1 :         for (u32 j = (i + 1); j < clusterInfo.rankList.size(); j++) {
     729            1 :             bool isErr = HasRepeatedIP(clusterInfo.rankList[i].deviceInfo.deviceIp,
     730            1 :                 clusterInfo.rankList[j].deviceInfo.deviceIp);
     731            1 :             if (isErr) {
     732            2 :                 std::string errormessage = "The device IP address " + std::string(clusterInfo.rankList[i].deviceInfo.deviceIp[0].GetReadableIP()) +
     733            4 :                                         " of rank " + std::to_string(clusterInfo.rankList[i].rankId) +
     734            3 :                                         " on node " +clusterInfo.rankList[i].serverId +
     735            4 :                                         " is the same as the device IP address " + std::string(clusterInfo.rankList[j].deviceInfo.deviceIp[0].GetReadableIP()) +
     736            4 :                                         " of rank " + std::to_string(clusterInfo.rankList[j].rankId) +
     737            2 :                                         " on node " + clusterInfo.rankList[j].serverId;
     738            7 :                 RPT_INPUT_ERR(true,
     739              :                     "EI0015",
     740              :                     std::vector<std::string>({"error_reason"}),
     741              :                     std::vector<std::string>({errormessage}));
     742              :                 
     743            1 :                 HCCL_ERROR("[%s][%s]%s",
     744              :                     LOG_KEYWORDS_INIT_GROUP.c_str(),
     745              :                     LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     746              :                     errormessage.c_str());
     747            1 :                 return HCCL_E_PARA;
     748            1 :             }
     749              :         }
     750              :     }
     751            0 :     return HCCL_SUCCESS;
     752            1 : }
     753              : 
     754            1 : HcclResult TopoInfoExchangeAgent::VerifyClusterBackupDeviceIP(RankTable_t &clusterInfo)
     755              : {
     756            1 :     if (localRankInfo_.deviceType != DevType::DEV_TYPE_910_93 || !isRetry_) {
     757              :         // 未开启重执行,则无需 backup device ip
     758            0 :         return HCCL_SUCCESS;
     759              :     }
     760            1 :     bool useSuperPodMode = false;
     761            1 :     CHK_RET(IsSuperPodMode(useSuperPodMode));
     762            1 :     if (!useSuperPodMode || clusterInfo.superPodNum == 1) {
     763              :         // 非多超节点场景,backup device ip 不做要求
     764            0 :         return HCCL_SUCCESS;
     765              :     }
     766            1 :     if (clusterInfo.rankList.size() == 1 || clusterInfo.serverList.size() == 1) {
     767              :         // 单卡或单机场景对 device ip 不做要求
     768            0 :         return HCCL_SUCCESS;
     769              :     }
     770              : 
     771            1 :     std::unordered_map<std::string, s32> devIp2PhyId;
     772            3 :     for (auto &rankInfo : clusterInfo.rankList) {
     773            4 :         for (auto &devIp : rankInfo.deviceInfo.deviceIp) {
     774            2 :             devIp2PhyId.emplace(devIp.GetReadableIP(), rankInfo.deviceInfo.devicePhyId);
     775              :         }
     776              :     }
     777              : 
     778            3 :     for (auto &rankInfo : clusterInfo.rankList) {
     779            4 :         for (auto &backupDevIp : rankInfo.deviceInfo.backupDeviceIp) {
     780            2 :             if (backupDevIp.IsInvalid()) {
     781            1 :                 continue;
     782              :             }
     783            2 :             std::string backupIpStr = std::string(backupDevIp.GetReadableIP());
     784            2 :             if (devIp2PhyId.find(backupIpStr) == devIp2PhyId.end()) {
     785            1 :                 HCCL_RUN_WARNING("[Verify][ClusterBackupDeviceIP]"
     786              :                     "backup devIp[%s] for devicePhyId[%d] is not in this comm. "
     787              :                     "The validation of this backup ip could not be verified! "
     788              :                     "Please notice it might be an invalid backup ip!",
     789              :                     backupIpStr.c_str(), rankInfo.deviceInfo.devicePhyId);
     790            1 :                 continue;
     791              :             }
     792              : 
     793            1 :             s32 backupDevPhyId = devIp2PhyId[backupIpStr];
     794            1 :             std::string errormessage;
     795            1 :             if (backupDevPhyId == rankInfo.deviceInfo.devicePhyId) {
     796            0 :                 errormessage = "PhyId[" + std::to_string(backupDevPhyId) + "] for backup devIp[" + backupIpStr +
     797            0 :                                 "] is the same with self devicephyId[" +
     798            0 :                                 std::to_string(rankInfo.deviceInfo.devicePhyId) +
     799            0 :                                 "]. Please do not use self ip as backup ip";
     800            0 :                 RPT_INPUT_ERR(true,
     801              :                     "EI0015",
     802              :                     std::vector<std::string>({"error_reason"}),
     803              :                     std::vector<std::string>({ errormessage }));
     804            0 :                 HCCL_ERROR("[%s][%s]errNo[0x%016llx], %s",
     805              :                     LOG_KEYWORDS_INIT_GROUP.c_str(),
     806              :                     LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     807              :                     HCOM_ERROR_CODE(HCCL_E_PARA),
     808              :                     errormessage.c_str());
     809            0 :                 return HCCL_E_PARA;
     810              :             }
     811              : 
     812            1 :             LinkTypeInServer linkType = LinkTypeInServer::RESERVED_LINK_TYPE;
     813            1 :             CHK_RET(hrtGetPairDeviceLinkType(rankInfo.deviceInfo.devicePhyId, backupDevPhyId, linkType));
     814            1 :             if (linkType != LinkTypeInServer::SIO_TYPE) {
     815            0 :                 RPT_INPUT_ERR(true,
     816              :                     "EI0014",
     817              :                     std::vector<std::string>({ "value", "variable" ,"expect" }),
     818              :                     std::vector<std::string>({ std::to_string(backupDevPhyId), " \"backup_device_ip of "\
     819              :                     "rank " + std::to_string(rankInfo.rankId) + "\" ", " \"is device_ip another Die under the same NPU\" " }));
     820            0 :                 errormessage = "Value " + std::to_string(backupDevPhyId) + " for rankTable variable \"backup_device_ip of "\
     821            0 :                     "rank " + std::to_string(rankInfo.rankId) + "\" is invalid, expected value \"is device_ip another Die under the same NPU\".";
     822              : 
     823            0 :                 HCCL_ERROR(
     824              :                     "[%s][%s]errNo[0x%016llx], %s",
     825              :                     LOG_KEYWORDS_INIT_GROUP.c_str(),
     826              :                     LOG_KEYWORDS_RANKTABLE_CHECK.c_str(),
     827              :                     HCOM_ERROR_CODE(HCCL_E_PARA),
     828              :                     errormessage.c_str());
     829            0 :                 return HCCL_E_PARA;
     830              :             }
     831            2 :         }
     832              :     }
     833            1 :     return HCCL_SUCCESS;
     834            1 : }
     835              : 
     836            1 : bool TopoInfoExchangeAgent::HasRepeatedIP(const std::vector<HcclIpAddress> &deviceAIP,
     837              :     const std::vector<HcclIpAddress> &deviceBIP) const
     838              : {
     839            1 :     for (u32 i = 0; i < deviceAIP.size(); i++) {
     840            1 :         for (u32 j = 0; j < deviceBIP.size(); j++) {
     841            1 :             if (deviceAIP[i] == deviceBIP[j]) {
     842            1 :                 HCCL_WARNING("device ip[%s] is repeated.", deviceAIP[i].GetReadableAddress());
     843            1 :                 return true;
     844              :             }
     845              :         }
     846              :     }
     847            0 :     return false;
     848              : }
     849              : 
     850            1 : HcclResult TopoInfoExchangeAgent::VerifyClusterRankID(const RankTable_t &clusterInfo) const
     851              : {
     852            1 :     if (clusterInfo.rankList.size() == 1) {
     853            0 :         return HCCL_SUCCESS;
     854              :     }
     855            1 :     for (u32 i = 0; i < (clusterInfo.rankList.size() - 1); i++) {
     856            1 :         for (u32 j = (i + 1); j < clusterInfo.rankList.size(); j++) {
     857            1 :             bool isErr = (clusterInfo.rankList[i].rankId == clusterInfo.rankList[j].rankId);
     858            1 :             if (isErr) {
     859            2 :                 std::string errormessage = "Rank ID " + std::to_string(clusterInfo.rankList[i].rankId) +
     860            4 :                                         " of device ID " + std::to_string(clusterInfo.rankList[i].deviceInfo.devicePhyId) + " on node " + clusterInfo.rankList[i].serverId +
     861            4 :                                         " is the same as that of device ID " + std::to_string(clusterInfo.rankList[j].deviceInfo.devicePhyId) +
     862            2 :                                         " on node " + clusterInfo.rankList[j].serverId;
     863            7 :                 RPT_INPUT_ERR(true,
     864              :                     "EI0015",
     865              :                     std::vector<std::string>({"error_reason"}),
     866              :                     std::vector<std::string>({errormessage}));
     867            1 :                 HCCL_ERROR("[%s][%s]%s",
     868              :                     LOG_KEYWORDS_INIT_GROUP.c_str(),
     869              :                     LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     870              :                     errormessage.c_str());
     871            1 :                     return HCCL_E_PARA;
     872            1 :             }
     873              :         }
     874              :     }
     875            0 :     return HCCL_SUCCESS;
     876            1 : }
     877              : 
     878            1 : HcclResult TopoInfoExchangeAgent::VerifyServerDevicePhysicID(const std::vector<RankInfo_t> &serverInfo) const
     879              : {
     880            1 :     if (serverInfo.size() == 1) {
     881            0 :         return HCCL_SUCCESS;
     882              :     }
     883            1 :     for (u32 i = 0; i < (serverInfo.size() - 1); i++) {
     884            1 :         for (u32 j = (i + 1); j < serverInfo.size(); j++) {
     885            1 :             bool isErr = (serverInfo[i].deviceInfo.devicePhyId == serverInfo[j].deviceInfo.devicePhyId);
     886            1 :             if (isErr) {
     887            2 :                 std::string errormessage = "Rank " + std::to_string(serverInfo[i].rankId) + " of node " +
     888            3 :                                         serverInfo[i].serverId +
     889            4 :                                         " has the same physical device ID " + std::to_string(serverInfo[i].deviceInfo.devicePhyId) + 
     890            3 :                                         " as the rank " + std::to_string(serverInfo[j].rankId);
     891            7 :                 RPT_INPUT_ERR(true,
     892              :                     "EI0015",
     893              :                     std::vector<std::string>({"error_reason"}),
     894              :                     std::vector<std::string>({errormessage}));
     895            1 :                 HCCL_ERROR("[%s][%s]%s",
     896              :                     LOG_KEYWORDS_INIT_GROUP.c_str(),
     897              :                     LOG_KEYWORDS_RANKTABLE_DETECT.c_str(),
     898              :                     errormessage.c_str());
     899            1 :                 return HCCL_E_PARA;                
     900            1 :             }
     901              :         }
     902              :     }
     903            0 :     return HCCL_SUCCESS;
     904            1 : }
     905              : 
     906            2 : HcclResult TopoInfoExchangeAgent::VerifyClusterSuperPodInfo(const std::vector<RankInfo_t> &rankInfo) const
     907              : {
     908            2 :     DevType curDevType = rankInfo.begin()->deviceInfo.deviceType;
     909            5 :     for (auto curRankInfo : rankInfo) {
     910            3 :         if (curDevType != curRankInfo.deviceInfo.deviceType) {
     911            0 :             HCCL_DEBUG("[Verify][SuperPodInfo] mix device type, does not need verify superPod info");
     912            0 :             return HCCL_SUCCESS;
     913              :         }
     914            3 :     }
     915              : 
     916            2 :     bool useSuperPodMode = false;
     917            2 :     CHK_RET(IsSuperPodMode(useSuperPodMode));
     918            2 :     CHK_PRT_RET(useSuperPodMode == false,
     919              :         HCCL_DEBUG("[Verify][SuperPodInfo] does not need verify superPod info"), HCCL_SUCCESS);
     920              : 
     921            2 :     std::string errormessage = "";
     922              :     // 获取每个超节点内的serverId
     923            2 :     std::map<std::string, std::set<std::string>> superPodSrvIdMap; // super_pod_id -> serverId
     924            2 :     std::map<std::string, std::unordered_map<u32, u32>> superPodSdidMap; // super_pod_id -> superDeviceId
     925            3 :     for (u32 i = 0; i < rankInfo.size(); i++) {
     926              :         // 超节点模式下, 校验superPodId和sdid值有效
     927            4 :         if ((rankInfo[i].superPodId.empty() || rankInfo[i].superDeviceId == INVALID_UINT) &&
     928            1 :             rankInfo[i].deviceInfo.deviceType == DevType::DEV_TYPE_910_93) {
     929           14 :             RPT_INPUT_ERR(true,
     930              :                 "EI0014",
     931              :                 std::vector<std::string>({ "value", "variable" ,"expect" }),
     932              :                 std::vector<std::string>({std::to_string(rankInfo[i].superDeviceId), "super_device_id",
     933              :                 "is less than the communication size " + std::to_string(rankInfo.size()) + " and must be unique"}));
     934            2 :             errormessage = "Value " + std::to_string(rankInfo[i].superDeviceId) + " for rankTable variable superDeviceId is invalid, "\
     935            3 :                             "expected value is less than the communication size " + std::to_string(rankInfo.size()) + " and must be unique.";
     936              : 
     937            1 :             HCCL_ERROR("[%s][%s]%s",
     938              :                 LOG_KEYWORDS_INIT_GROUP.c_str(),
     939              :                 LOG_KEYWORDS_RANKTABLE_CHECK.c_str(),
     940              :                 errormessage.c_str());
     941            2 :             return HCCL_E_PARA;
     942              :         }
     943              : 
     944            2 :         auto iter = superPodSrvIdMap.find(rankInfo[i].superPodId);
     945            2 :         if (iter == superPodSrvIdMap.end()) {
     946            1 :             std::set<std::string> serverIdSet;
     947            1 :             serverIdSet.insert(rankInfo[i].serverId);
     948            1 :             superPodSrvIdMap.insert({rankInfo[i].superPodId, serverIdSet});
     949            2 :         } else if (iter->second.find(rankInfo[i].serverId) == iter->second.end()) {
     950            0 :             iter->second.insert(rankInfo[i].serverId);
     951              :         }
     952              : 
     953            2 :         auto it = superPodSdidMap.find(rankInfo[i].superPodId);
     954            2 :         if (it == superPodSdidMap.end()) {
     955            1 :                 std::unordered_map<u32, u32> superDeviceIdSet;
     956            1 :             superDeviceIdSet.insert({rankInfo[i].superDeviceId, rankInfo[i].rankId});
     957            1 :             superPodSdidMap.insert({rankInfo[i].superPodId, superDeviceIdSet});
     958            2 :         } else if (it->second.find(rankInfo[i].superDeviceId) == it->second.end()) {
     959            0 :             it->second.insert({rankInfo[i].superDeviceId, rankInfo[i].rankId});
     960              :         } else {
     961              :             // 超节点内superDeviceId在超节点内唯一
     962            1 :             if (it->second.find(rankInfo[i].superDeviceId) != it->second.end()) {
     963           15 :                 RPT_INPUT_ERR(true,
     964              :                     "EI0014",
     965              :                     std::vector<std::string>({ "value", "variable" ,"expect" }),
     966              :                     std::vector<std::string>({std::to_string(rankInfo[i].superDeviceId), " \"Device Id of server Id " + rankInfo[i].serverId + "\" ", "is unique"}));
     967            2 :                 errormessage = "Value " + std::to_string(rankInfo[i].superDeviceId) + " for rankTable "\
     968            2 :                     "variable \"Device Id of server Id " + rankInfo[i].serverId + "\" is invalid, expected value is unique.";
     969            1 :                 HCCL_ERROR("[%s][%s]%s",
     970              :                     LOG_KEYWORDS_INIT_GROUP.c_str(),
     971              :                     LOG_KEYWORDS_RANKTABLE_CHECK.c_str(),
     972              :                     errormessage.c_str());
     973            1 :                 return HCCL_E_PARA;
     974              :             }
     975              :         }
     976              :     }
     977              : 
     978              :     // 校验每个超节点内的server数量一致
     979            0 :     u32 serverNumPerPod = 0;
     980            0 :     for (auto iter = superPodSrvIdMap.begin(); iter != superPodSrvIdMap.end(); ++iter) {
     981            0 :         if (iter == superPodSrvIdMap.begin()) {
     982            0 :             serverNumPerPod = superPodSrvIdMap.begin()->second.size();
     983              :         }
     984            0 :         u32 serverNumCurPod = iter->second.size();
     985            0 :         if (serverNumPerPod != serverNumCurPod) {
     986            0 :             HCCL_DEBUG("[Verify][SuperPodInfo]serverNum[%u] in superPod[%s] and serverNum[%u] in superPod[%s] "\
     987              :             "are different.", serverNumPerPod, superPodSrvIdMap.begin()->first.c_str(),
     988              :             serverNumCurPod, iter->first.c_str());
     989              :         }
     990              :     }
     991              : 
     992            0 :     return HCCL_SUCCESS;
     993            8 : }
     994              : 
     995            7 : HcclResult TopoInfoExchangeAgent::VerifyClusterTlsConsistency(const RankTable_t &clusterInfo)
     996              : {
     997            7 :     bool isSupportCheckTlsStatus = true; // 用于标识是否存在不支持查询Tls开关状态的情况
     998            7 :     bool isTlsConsistent = true; // 用于标识TLS开关状态是否一致
     999            7 :     std::unordered_map<std::string, std::vector<u32>> tlsEnableRank;
    1000            7 :     std::unordered_map<std::string, std::vector<u32>> tlsDisableRank;
    1001            7 :     std::unordered_map<std::string, std::vector<u32>> tlsUnknownRank;
    1002           35 :     for (auto& rankInfo : clusterInfo.rankList) {
    1003           28 :         if (rankInfo.tlsStatus == TlsStatus::ENABLE) {
    1004           15 :             AddRankInfoToTlsStatusMap(rankInfo, tlsEnableRank);
    1005           13 :         } else if (rankInfo.tlsStatus == TlsStatus::DISABLE) {
    1006            9 :             AddRankInfoToTlsStatusMap(rankInfo, tlsDisableRank);
    1007              :         } else {
    1008            4 :             isSupportCheckTlsStatus = false;
    1009            4 :             AddRankInfoToTlsStatusMap(rankInfo, tlsUnknownRank);
    1010              :         }
    1011              :     }
    1012              :     // 将不一致的卡信息汇总成一个string
    1013           14 :     std::string tlsInconsistentEnableStr = "";
    1014           14 :     std::string tlsInconsistentDisableStr = "";
    1015            7 :     std::string tlsInconsistentTlsType = "";
    1016            7 :     if (!tlsEnableRank.empty() && !tlsDisableRank.empty()) {
    1017            5 :         isTlsConsistent = false;
    1018            5 :         tlsInconsistentTlsType = (tlsEnableRank.size() >= tlsDisableRank.size()) ? "Disable" : "Enable";
    1019            5 :         GenerateTlsStatusStr(tlsInconsistentEnableStr, tlsEnableRank);
    1020            5 :         GenerateTlsStatusStr(tlsInconsistentDisableStr, tlsDisableRank);
    1021              :     }
    1022              :     // 将不支持查询的卡的信息汇总成一个string
    1023            7 :     std::string tlsUnknownRankStr = "";
    1024            7 :     if (!isSupportCheckTlsStatus) {
    1025            3 :         GenerateTlsStatusStr(tlsUnknownRankStr, tlsUnknownRank);
    1026              :     }
    1027           11 :     tlsUnknownRankStr = tlsUnknownRankStr.empty() ? "N/A" : tlsUnknownRankStr;
    1028              :     // 四种不同情况
    1029            7 :     if (isTlsConsistent && isSupportCheckTlsStatus) {
    1030              :     // 1.通信域所有卡都支持查询TLS开关状态,并且TLS开关状态都是一致的。
    1031            1 :         HCCL_INFO("[Verify][TlsConsistency] All ranks tlsStatus are consistent");
    1032            6 :     } else if (!isTlsConsistent && isSupportCheckTlsStatus) {
    1033              :         // 2.通信域所有卡都支持查询TLS开关状态,但是TLS开关状态存在不一致,报错。
    1034            3 :         ReportTlsConfigurationError(tlsInconsistentTlsType, tlsInconsistentEnableStr, tlsInconsistentDisableStr, "N/A");
    1035            3 :         return HCCL_E_PARA;
    1036            3 :     } else if (isTlsConsistent && !isSupportCheckTlsStatus) {
    1037              :     // 3.通信域内的部分卡不支持查询TLS开关状态,目前能查询到的卡的TLS开关状态是一致的,打印warning提醒
    1038            1 :         HCCL_RUN_WARNING("[Verify][TlsConsistency] Some ranks do not support to check tlsStatus, " \
    1039              :             "not support serverId/rankId: %s", tlsUnknownRankStr.c_str());
    1040              :     } else {
    1041              :         // 4.通信域内的部分卡不支持查询TLS开关状态,但是目前能查询到的卡的TLS开关状态已经不一致,报错
    1042            2 :         ReportTlsConfigurationError(tlsInconsistentTlsType, tlsInconsistentEnableStr, tlsInconsistentDisableStr, tlsUnknownRankStr);
    1043            2 :         return HCCL_E_PARA;
    1044              :     }
    1045            2 :     return HCCL_SUCCESS;
    1046            7 : }
    1047              : 
    1048           28 : void TopoInfoExchangeAgent::AddRankInfoToTlsStatusMap(const RankInfo_t &rankInfo,
    1049              :         std::unordered_map<std::string, std::vector<u32>> &tlsStatusRankMap)
    1050              : {
    1051           28 :     auto iter = tlsStatusRankMap.find(rankInfo.serverId);
    1052           28 :     if (iter == tlsStatusRankMap.end()) {
    1053           15 :         std::vector<u32> tlsStatusRankList;
    1054           15 :         tlsStatusRankList.push_back(rankInfo.rankId);
    1055           15 :         tlsStatusRankMap.insert({rankInfo.serverId, tlsStatusRankList});
    1056           15 :     } else {
    1057           13 :         iter->second.push_back(rankInfo.rankId); 
    1058              :     }
    1059           56 :     return;
    1060              : }
    1061              : 
    1062           13 : void TopoInfoExchangeAgent::GenerateTlsStatusStr(std::string &tlsStatusStr,
    1063              :         const std::unordered_map<std::string, std::vector<u32>> &tlsStatusRankMap)
    1064              : {
    1065           26 :     for (const auto& rankIt : tlsStatusRankMap) {
    1066           13 :         tlsStatusStr += ("[" + rankIt.first + "/");
    1067           35 :         for (const auto& rank : rankIt.second) {
    1068           22 :             tlsStatusStr += std::to_string(rank) + ",";
    1069              :         }
    1070           13 :         if (!tlsStatusStr.empty() && tlsStatusStr.back() == ',') {
    1071           13 :             tlsStatusStr = tlsStatusStr.substr(0, tlsStatusStr.size() - 1); // 删除逗号
    1072              :         }
    1073           13 :         tlsStatusStr += "];";
    1074              :     }
    1075           13 :     return;
    1076              : }
    1077              : 
    1078            5 : void TopoInfoExchangeAgent::ReportTlsConfigurationError(const std::string& tlsInconsistentTlsType,
    1079              :         const std::string& tlsInconsistentEnableStr, const std::string& tlsInconsistentDisableStr, const std::string& tlsUnknownRankStr)
    1080              : {
    1081           10 :     std::string errormessage = "Value " + tlsInconsistentTlsType + " for config \"tls\" is invalid. Expected: \"All ranks are consistent. Current status: "\
    1082            5 :     "rankList for enabled tls: " + tlsInconsistentEnableStr + " rankList for disabled tls:" + tlsInconsistentDisableStr + " rankList for query failure tls:" + tlsUnknownRankStr + ".\"";
    1083           70 :     RPT_INPUT_ERR(true,
    1084              :     "EI0016",
    1085              :     std::vector<std::string>({"value", "variable", "expect"}),
    1086              :     std::vector<std::string>({tlsInconsistentTlsType, " \"tls\" ",
    1087              :         " \"All ranks are consistent. Current status: rankList for enabled tls:" + tlsInconsistentEnableStr + "; "\
    1088              :         "rankList for disabled tls:" + tlsInconsistentDisableStr + " rankList for query failure tls:" + tlsUnknownRankStr + ".\" "}));
    1089            5 :     HCCL_ERROR("[%s][%s] %s", LOG_KEYWORDS_INIT_GROUP.c_str(), LOG_KEYWORDS_RANKTABLE_CHECK.c_str(), errormessage.c_str());
    1090           20 : }
    1091              : }
        

Generated by: LCOV version 2.0-1