LCOV - code coverage report
Current view: top level - legacy/ascend910/framework/cluster_maintenance/recovery/operator_retry - opretry_connection.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.8 % 361 317
Test Date: 2026-07-28 12:11:00 Functions: 96.8 % 31 30

            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 "opretry_connection.h"
      12              : #include <fstream>
      13              : #include <nlohmann/json.hpp>
      14              : #include "sal_pub.h"
      15              : #include "hccl_network_pub.h"
      16              : #include "externalinput_pub.h"
      17              : #include "adapter_rts_common.h"
      18              : #include "opretry_connection_pub.h"
      19              : 
      20              : namespace hccl {
      21              : UniversalConcurrentMap<std::string, OpRetryConnection::OpRetryConnectionPtr> *OpRetryConnection::instance_ = nullptr;
      22              : std::mutex OpRetryConnection::lock_;
      23              : bool OpRetryConnection::enable_ = true;
      24              : 
      25              : /** OpRetryConnectionPub 封装一层OpRetryConnection接口 */
      26            5 : void OpRetryConnectionPub::SetOpRetryConnEnable(bool enable)
      27              : {
      28            5 :     OpRetryConnection::SetOpRetryConnEnable(enable);
      29            5 : }
      30              : 
      31            4 : bool OpRetryConnectionPub::IsOpRetryConnEnable()
      32              : {
      33            4 :     return OpRetryConnection::IsOpRetryConnEnable();
      34              : }
      35              : 
      36            6 : HcclResult OpRetryConnectionPub::Init(const std::string &group, u32 rankSize, const OpRetryServerInfo& serverInfo,
      37              :     const OpRetryAgentInfo& agentInfo, u32 rootRank)
      38              : {
      39            6 :     return OpRetryConnection::Init(group, rankSize, serverInfo, agentInfo, rootRank);
      40              : }
      41              : 
      42            4 : void OpRetryConnectionPub::DeInit(const std::string &group)
      43              : {
      44            4 :     OpRetryConnection::DelInstance(group);
      45            4 : }
      46              : 
      47            2 : HcclResult OpRetryConnectionPub::GetConns(const std::string &group, bool &isRoot, std::shared_ptr<HcclSocket> &agent,
      48              :     std::map<u32, std::shared_ptr<HcclSocket>> &server)
      49              : {
      50            2 :     if (!IsOpRetryConnEnable()) {
      51            1 :         HCCL_INFO("[OpRetryConnection][Init] op retry is disable, so don't need get conns");
      52            1 :         return HCCL_SUCCESS;
      53              :     }
      54              : 
      55            1 :     OpRetryConnection::OpRetryConnectionPtr conn;
      56            1 :     CHK_RET(OpRetryConnection::GetInstance(group, conn));
      57              : 
      58            1 :     isRoot = conn->IsRoot();
      59            1 :     CHK_RET(conn->GetAgentSocket(agent));
      60            1 :     if (isRoot) {
      61            1 :         CHK_RET(conn->GetServerSockets(server));
      62              :     }
      63              : 
      64            1 :     return HCCL_SUCCESS;
      65            1 : }
      66              : /** OpRetryConnectionPub 封装层结束 */
      67              : 
      68            9 : OpRetryConnection::OpRetryConnection()
      69              : {
      70            9 : }
      71              : 
      72            9 : OpRetryConnection::~OpRetryConnection()
      73              : {
      74            9 :     DeInit();
      75            9 : }
      76              : 
      77            5 : void OpRetryConnection::SetOpRetryConnEnable(bool enable)
      78              : {
      79            5 :     enable_ = enable;
      80            5 : }
      81              : 
      82           11 : bool OpRetryConnection::IsOpRetryConnEnable()
      83              : {
      84           11 :     return enable_;
      85              : }
      86              : 
      87            7 : HcclResult OpRetryConnection::Init(const std::string &group, u32 rankSize, const OpRetryServerInfo& serverInfo,
      88              :     const OpRetryAgentInfo& agentInfo, u32 rootRank)
      89              : {
      90            7 :     if (!IsOpRetryConnEnable()) {
      91            1 :         HCCL_INFO("[OpRetryConnection][Init] op retry is disable");
      92            1 :         return HCCL_SUCCESS;
      93              :     }
      94            6 :     u32 rankId = agentInfo.userRank;
      95            6 :     HcclIpAddress serverIp = serverInfo.hostIP;
      96            6 :     u32 serverPort = serverInfo.hostPort == HCCL_INVALID_PORT
      97            6 :         ? GetServerPort() + serverInfo.devId : serverInfo.hostPort;
      98            6 :     HcclIpAddress localIp = agentInfo.hostIP;
      99            6 :     if (serverIp.IsInvalid() || localIp.IsInvalid()) {
     100            2 :         HCCL_ERROR("[OpRetryConnection][Init] serverIp [%s] or localIp [%s] is invalid, "
     101              :             "check whether the value of host_ip in ranktable is correct.",
     102              :             serverIp.GetReadableIP(), localIp.GetReadableIP());
     103            2 :         return HCCL_E_PARA;
     104              :     }
     105            4 :     if (rankId >= rankSize || rankSize == 0 || rootRank >= rankSize) {
     106            0 :         HCCL_ERROR("[OpRetryConnection][Init] opRetryConnection input params invalid,"
     107              :             "rankId [%u] rankSize [%u] serverIp [%s] localIp [%s] rootRank [%u]",
     108              :             rankId, rankSize, serverIp.GetReadableIP(), localIp.GetReadableIP(), rootRank);
     109            0 :         return HCCL_E_PARA;
     110              :     }
     111              : 
     112            4 :     HCCL_INFO("[OpRetryConnection][Init] group[%s] rankId [%u] rankSize [%u] serverIp [%s] localIp [%s] rootRank [%u]",
     113              :         group.c_str(), rankId, rankSize, serverIp.GetReadableIP(), localIp.GetReadableIP(), rootRank);
     114              : 
     115            4 :     OpRetryConnectionPtr conn;
     116            4 :     CHK_RET(GetInstance(group, conn, true));
     117            4 :     conn->SetGroup(group);
     118            4 :     if (conn->Init(rankId, rankSize, serverIp, serverPort, serverInfo.devId, localIp, rootRank) != HCCL_SUCCESS) {
     119            3 :         HCCL_ERROR(
     120              :             "[OpRetryConnection][Init] group[%s] rankId [%u] rankSize [%u] serverIp [%s] localIp [%s] rootRank [%u] failed",
     121              :             group.c_str(), rankId, rankSize, serverIp.GetReadableIP(), localIp.GetReadableIP(), rootRank);
     122            3 :         HCCL_ERROR("There maybe some reasons to cause this error:");
     123            3 :         HCCL_ERROR("1. The port may have been used so we will bind error. OpRetry used port range [%u-%u]",
     124              :             serverPort, serverPort + OP_RETRY_CONN_PORT_MAX_RANGE);
     125            3 :         HCCL_ERROR("2. Somebody may have already listen on those ports, so we connect to wrong server "
     126              :             "and we will meet 'Recv unmatched ack' error");
     127            3 :         HCCL_ERROR("You may can set system reserved port to avoid this error by:");
     128            3 :         HCCL_ERROR("sysctl -w net.ipv4.ip_local_reserved_ports=%u-%u",
     129              :             serverPort, serverPort + OP_RETRY_CONN_PORT_MAX_RANGE);
     130            3 :         return HCCL_E_INTERNAL;
     131              :     }
     132              : 
     133            1 :     return HCCL_SUCCESS;
     134            6 : }
     135              : 
     136            5 : HcclResult OpRetryConnection::GetInstance(const std::string &group, OpRetryConnectionPtr &conn, bool forceNew)
     137              : {
     138              :     // instance_本身是个指针,需要lock_锁来保护
     139            5 :     std::lock_guard<std::mutex> lockGaurd(lock_);
     140            5 :     if (instance_ == nullptr) {
     141            4 :         instance_ = new (std::nothrow) UniversalConcurrentMap<std::string, OpRetryConnectionPtr>();
     142            4 :         CHK_PTR_NULL(instance_);
     143              :     }
     144              : 
     145            5 :     std::lock_guard<std::shared_timed_mutex> guard(instance_->GetMtx());
     146            5 :     if (forceNew || instance_->FindLockFree(group) == instance_->EndLockFree()) {
     147            4 :         OpRetryConnectionPtr tmpConn;
     148            4 :         EXCEPTION_CATCH(tmpConn = std::make_shared<OpRetryConnection>(), return HCCL_E_PTR);
     149            4 :         instance_->EmplaceLockFree(group, tmpConn);
     150            4 :     }
     151              : 
     152            5 :     auto it = instance_->FindLockFree(group);
     153            5 :     CHK_PRT_RET(it == instance_->EndLockFree(),
     154              :         HCCL_ERROR("[OpRetryConnection][GetInstance] create connection failed in group [%s]", group.c_str()), HCCL_E_MEMORY);
     155            5 :     conn = it->second;
     156            5 :     CHK_SMART_PTR_NULL(conn);
     157              : 
     158            5 :     return HCCL_SUCCESS;
     159            5 : }
     160              : 
     161            4 : HcclResult OpRetryConnection::DelInstance(const std::string &group)
     162              : {
     163              :     // instance_本身是个指针,需要lock_锁来保护
     164            4 :     std::lock_guard<std::mutex> lockGuard(lock_);
     165            4 :     if (instance_) {
     166            4 :         instance_->Erase(group);
     167            4 :         if (instance_->Size() == 0) {
     168            4 :             delete instance_;
     169            4 :             instance_ = nullptr;
     170              :         }
     171              :     }
     172              : 
     173            4 :     return HCCL_SUCCESS;
     174            4 : }
     175              : 
     176            7 : HcclResult OpRetryConnection::Init(u32 rankId, u32 rankSize, const HcclIpAddress &serverIp, u32 serverPort,
     177              :     s32 serverDevId, const HcclIpAddress &localIp, u32 rootRank)
     178              : {
     179            7 :     if (rankId >= rankSize || rankSize == 0 || serverIp.IsInvalid() || rootRank >= rankSize || localIp.IsInvalid()) {
     180            0 :         HCCL_ERROR(
     181              :             "[OpRetryConnection][Init] Invalid params, rankId [%u] rankSize [%u] serverIp [%s] localIp [%s] rootRank [%u]",
     182              :             rankId, rankSize, serverIp.GetReadableIP(), localIp.GetReadableIP(), rootRank);
     183            0 :         return HCCL_E_PARA;
     184              :     }
     185              : 
     186            7 :     rankId_ = rankId;
     187            7 :     rankSize_ = rankSize;
     188            7 :     serverIp_ = serverIp;
     189            7 :     serverPort_ = serverPort;
     190            7 :     localIp_ = localIp;
     191            7 :     rootRank_ = rootRank;
     192              : 
     193            7 :     HCCL_INFO("[OpRetryConnection][Init] rankId[%u] rankSize[%d] rootRank[%u] serverIp[%s:%u] serverDevId[%d]", rankId_,
     194              :         rankSize_, rootRank_, serverIp.GetReadableIP(), serverPort_, serverDevId);
     195              : 
     196            7 :     CHK_RET(InitHcclNet());
     197              : 
     198            7 :     if (IsRoot()) {
     199            7 :         CHK_PRT_RET(StartListen() != HCCL_SUCCESS,
     200              :             HCCL_ERROR("[OpRetryConnection][Init] Start listen failed, serverIp_[%s] serverPort_[%u]",
     201              :             serverIp_.GetReadableIP(), serverPort_), HCCL_E_TCP_CONNECT);
     202              :     }
     203              : 
     204            7 :     auto startTime = std::chrono::steady_clock::now();
     205            7 :     auto timeout = std::chrono::seconds(GetExternalInputHcclLinkTimeOut());
     206            7 :     u32 retryConnectTimes = 0;
     207              :     do {
     208           10 :         CHK_PRT_RET((std::chrono::steady_clock::now() - startTime) > timeout,
     209              :             HCCL_ERROR("[OpRetryConnection][Init] Connect to server timeout [%ld s], serverIp_[%s] serverPort_[%u]",
     210              :             timeout, serverIp_.GetReadableIP(), serverPort_), HCCL_E_TCP_CONNECT);
     211              : 
     212           10 :         auto ret = Connect();
     213           10 :         if (ret == HCCL_SUCCESS) {
     214            5 :             break;
     215            5 :         } else if (ret == HCCL_E_AGAIN) {
     216            3 :             HCCL_ERROR("[OpRetryConnection][Init] Connect to server failed, serverIp_[%s] serverPort_[%u], we try again",
     217              :                 serverIp_.GetReadableIP(), serverPort_);
     218            3 :             retryConnectTimes++;
     219            3 :             SaluSleep(TEN_MILLISECOND_OF_USLEEP);
     220            3 :             continue;
     221              :         } else {
     222            2 :             HCCL_ERROR("[OpRetryConnection][Init] Connect to server failed, serverIp_[%s] serverPort_[%u]",
     223              :                 serverIp_.GetReadableIP(), serverPort_);
     224            2 :             return ret;
     225              :         }
     226            3 :     } while (true);
     227              : 
     228            5 :     if (retryConnectTimes > 0) {
     229            1 :         HCCL_ERROR("[OpRetryConnection][Init] Client reconnect %u times to success, "
     230              :             "so the above or this error log can be ignored", retryConnectTimes);
     231              :     }
     232              : 
     233            5 :     if (IsRoot()) {
     234            5 :         CHK_RET(WaitAcceptFinish());
     235              :     }
     236              : 
     237            4 :     HCCL_INFO("[OpRetryConnection][Init] success rankId[%u] rankSize[%d] rootRank[%u] serverIp[%s:%u]", rankId_,
     238              :         rankSize_, rootRank_, serverIp.GetReadableIP(), serverPort_);
     239              : 
     240            4 :     return HCCL_SUCCESS;
     241              : }
     242              : 
     243           12 : HcclResult OpRetryConnection::DeInit()
     244              : {
     245           12 :     HCCL_INFO("[OpRetryConnection][Deinit] tag[%s] ready to deinit", tag_.c_str());
     246              :     /* 等待后台线程结束 */
     247           12 :     backgroudThreadStop_ = true;
     248           12 :     if (backgroudThread_.joinable()) {
     249            7 :         backgroudThread_.join();
     250              :     }
     251              : 
     252              :     /* 关闭所有连接 */
     253           17 :     for (auto &socket: connectionSockets_) {
     254            5 :         socket.second->Close();
     255              :     }
     256           12 :     connectionSockets_.clear();
     257           12 :     StopListen();
     258              : 
     259           12 :     if (socket_) {
     260            5 :         HCCL_INFO("[OpRetryConnection] close socket");
     261            5 :         socket_->Close();
     262            5 :         socket_ = nullptr;
     263              :     }
     264              : 
     265              :     /* 释放NetCtx资源 */
     266           12 :     if (serverNetCtx_) {
     267            7 :         HcclNetCloseDev(serverNetCtx_);
     268            7 :         serverNetCtx_ = nullptr;
     269              :     }
     270              : 
     271           12 :     if (clientNetCtx_) {
     272            5 :         HcclNetCloseDev(clientNetCtx_);
     273            5 :         clientNetCtx_ = nullptr;
     274              :     }
     275              : 
     276           12 :     if (hcclNetInit_) {
     277            7 :         HcclNetDeInit(NICDeployment::NIC_DEPLOYMENT_HOST, devicePhysicID_, deviceLogicalID_);
     278            7 :         hcclNetInit_ = false;
     279              :     }
     280              : 
     281           12 :     return HCCL_SUCCESS;
     282              : }
     283              : 
     284            1 : HcclResult OpRetryConnection::GetAgentSocket(std::shared_ptr<HcclSocket> &sock)
     285              : {
     286            1 :     if (socket_) {
     287            1 :         sock = socket_;
     288            1 :         return HCCL_SUCCESS;
     289              :     }
     290              : 
     291            0 :     HCCL_ERROR("[OpRetryConnection][GetAgentSocket] socket is nullptr");
     292            0 :     return HCCL_E_UNAVAIL;
     293              : }
     294              : 
     295            1 : HcclResult OpRetryConnection::GetServerSockets(std::map<u32, std::shared_ptr<HcclSocket>> &socks)
     296              : {
     297            1 :     if (!IsRoot()) {
     298            0 :         HCCL_ERROR("[OpRetryConnection][GetServerSockets] rank[%u] is not root rank [%u], so no server sockets",
     299              :             rankId_, rootRank_);
     300            0 :         return HCCL_E_UNAVAIL;
     301              :     }
     302              : 
     303            1 :     if (!connectionSockets_.empty() && connectionSockets_.size() == rankSize_) {
     304            1 :         socks = connectionSockets_;
     305            1 :         return HCCL_SUCCESS;
     306              :     }
     307              : 
     308            0 :     HCCL_ERROR("[OpRetryConnection][GetServerSockets] connection sockets count [%u] rankSize [%u]",
     309              :         connectionSockets_.size(), rankSize_);
     310            0 :     return HCCL_E_UNAVAIL;
     311              : }
     312              : 
     313            7 : HcclResult OpRetryConnection::InitHcclNet()
     314              : {
     315            7 :     CHK_RET(hrtGetDevice(&deviceLogicalID_));
     316            7 :     CHK_RET(hrtGetDevicePhyIdByIndex(deviceLogicalID_, devicePhysicID_));
     317            7 :     HCCL_INFO("[OpRetryConnection][InitHcclNet] deviceLogicalID_[%d] devicePhysicID_[%u]", deviceLogicalID_, devicePhysicID_);
     318              : 
     319            7 :     CHK_RET(HcclNetInit(NICDeployment::NIC_DEPLOYMENT_HOST, devicePhysicID_, deviceLogicalID_, true));
     320            7 :     hcclNetInit_ = true;
     321              : 
     322            7 :     return HCCL_SUCCESS;
     323              : }
     324              : 
     325            1 : HcclResult OpRetryConnection::LoadHostWhiteList(const std::string &whiteListFile)
     326              : {
     327            1 :     if (!whitelist_.empty()) {
     328            0 :         return HCCL_SUCCESS;
     329              :     }
     330              : 
     331            1 :     nlohmann::json fileContent;
     332            1 :     std::ifstream infile(whiteListFile.c_str(), std::ifstream::in);
     333            1 :     CHK_PRT_RET(!infile, HCCL_ERROR("[OpRetryConnection][LoadHostWhiteList]open file %s failed", whiteListFile.c_str()),
     334              :         HCCL_E_PARA);
     335              : 
     336              :     try {
     337            1 :         infile >> fileContent; // 将文件内容读取到json对象内
     338            0 :     } catch (...) {
     339            0 :         HCCL_ERROR("[OpRetryConnection][LoadHostWhiteList]load file[%s] to json fail. please check json file format.",
     340              :             whiteListFile.c_str());
     341            0 :         infile.close();
     342            0 :         return HCCL_E_INTERNAL;
     343            0 :     }
     344            1 :     infile.close();
     345              : 
     346            1 :     CHK_PRT_RET(fileContent.find("host_ip") == fileContent.end(),
     347              :         HCCL_ERROR("[OpRetryConnection][LoadHostWhiteList] whitelist don't have host_ip"), HCCL_E_INTERNAL);
     348            1 :     nlohmann::json hostWhitelist = fileContent["host_ip"];
     349            2 :     for (auto& ipJson : hostWhitelist) {
     350            1 :         std::string ipStr;
     351              :         try {
     352            1 :             ipStr = ipJson.get<std::string>();
     353            0 :         } catch (...) {
     354            0 :             HCCL_ERROR("[OpRetryConnection][LoadHostWhiteList]get ipStr from ipJson failed, please check host white list");
     355            0 :             return HCCL_E_PARA;
     356            0 :         }
     357            1 :         HcclIpAddress ip(ipStr);
     358            1 :         CHK_PRT_RET(ip.IsInvalid(),
     359              :             HCCL_ERROR("[OpRetryConnection][LoadHostWhiteList]string[%s] is invalid ip", ipStr.c_str()), HCCL_E_PARA);
     360            1 :         whitelist_.push_back(ip);
     361            1 :     }
     362              : 
     363            1 :     return HCCL_SUCCESS;
     364            1 : }
     365              : 
     366            7 : HcclResult OpRetryConnection::StartListen()
     367              : {
     368            7 :     CHK_RET(HcclNetOpenDev(&serverNetCtx_, NicType::HOST_NIC_TYPE, devicePhysicID_, deviceLogicalID_, localIp_));
     369            7 :     CHK_PTR_NULL(serverNetCtx_);
     370              : 
     371            7 :     auto enableWhiteList_ = GetExternalInputHcclEnableWhitelist();
     372            7 :     if (enableWhiteList_ != 0) {
     373            1 :         CHK_RET(GetHostSocketWhiteList());
     374              :     }
     375              : 
     376            7 :     EXCEPTION_CATCH((listenSocket_ = std::make_shared<HcclSocket>(serverNetCtx_, serverPort_)), return HCCL_E_PTR);
     377            7 :     CHK_SMART_PTR_NULL(listenSocket_);
     378            7 :     CHK_RET(listenSocket_->Init());
     379            7 :     CHK_RET(listenSocket_->Listen());
     380              : 
     381            7 :     if (enableWhiteList_ != 0) {
     382            1 :         CHK_RET(AddListenSocketWhiteList());
     383              :     }
     384              : 
     385            7 :     HCCL_INFO("[OpRetryConnection] Server start with host ip[%s] and port[%u]", serverIp_.GetReadableAddress(), serverPort_);
     386              : 
     387              :     /* 拉起后台线程,在线程中进行异步接收,这样不会阻塞当前主线程,可以进行后续
     388              :      * 用户需要主动调用WaitAcceptFinished()去等待建链结束
     389              :      */
     390            7 :     acceptFinished_ = false;
     391            7 :     backgroudThreadStop_ = false;
     392            7 :     std::thread thread(&OpRetryConnection::RunAccept, this);
     393            7 :     backgroudThread_ = std::move(thread);
     394              : 
     395            7 :     return HCCL_SUCCESS;
     396            7 : }
     397              : 
     398           17 : HcclResult OpRetryConnection::StopListen()
     399              : {
     400           17 :     if (listenSocket_) {
     401            7 :         HCCL_INFO("[OpRetryConnection] Server stop listen socket");
     402            7 :         if (enableWhitelist_ && !wlistInfosVec_.empty()) {
     403            0 :             listenSocket_->DelWhiteList(wlistInfosVec_);
     404            0 :             enableWhitelist_ = false;
     405            0 :             wlistInfosVec_.clear();
     406              :         }
     407              : 
     408            7 :         listenSocket_->DeInit();
     409            7 :         listenSocket_ = nullptr;
     410              :     }
     411              : 
     412           17 :     return HCCL_SUCCESS;
     413              : }
     414              : 
     415            7 : HcclResult OpRetryConnection::Accept()
     416              : {
     417            7 :     auto startTime = std::chrono::steady_clock::now();
     418            7 :     auto timeout = std::chrono::seconds(GetExternalInputHcclLinkTimeOut());
     419            7 :     auto tag = GetTag();
     420            7 :     std::shared_ptr<HcclSocket> socket = nullptr;
     421              : 
     422              :     /* 这里我们按照通信域中rank数目依次accept所有连接 */
     423            7 :     u32 expectAcceptNum = rankSize_;
     424           21 :     while (expectAcceptNum > 0) {
     425            9 :         if (backgroudThreadStop_) {
     426            2 :             HCCL_ERROR("[OpRetryConnection][Accept] OpRetryConnection in acceptting but stop, rankSize_[%u] accept link[%u]",
     427              :                 rankSize_, rankSize_ - expectAcceptNum);
     428            2 :             return HCCL_E_INTERNAL;
     429              :         }
     430              : 
     431            7 :         if ((std::chrono::steady_clock::now() - startTime) > timeout) {
     432            0 :             HCCL_ERROR("[OpRetryConnection][Accept] OpRetryConnection accept timeout! timeout[%d s]",
     433              :                 GetExternalInputHcclLinkTimeOut());
     434            0 :             return HCCL_E_TIMEOUT;
     435              :         }
     436              : 
     437            7 :         if (listenSocket_->Accept(tag, socket) == HCCL_SUCCESS) {
     438            5 :             HCCL_INFO("[OpRetryConnection][Accept] accept peer ip[%s]", socket->GetRemoteIp().GetReadableIP());
     439              :             // 因为socket是全双工的,所以Server与Client侧均可以先发送,再接收
     440            5 :             CHK_RET(SendAckInfo(socket));
     441            5 :             CHK_RET(RecvMetaInfo(socket));
     442            5 :             expectAcceptNum--;
     443              :         }
     444              :     }
     445              : 
     446            5 :     return HCCL_SUCCESS;
     447            7 : }
     448              : 
     449            5 : HcclResult OpRetryConnection::WaitAcceptFinish()
     450              : {
     451            5 :     auto startTime = std::chrono::steady_clock::now();
     452            5 :     auto timeout = std::chrono::seconds(GetExternalInputHcclLinkTimeOut());
     453              : 
     454              :     while (true) {
     455     14685393 :         if (backgroudThreadStop_) {
     456            1 :             HCCL_ERROR("[OpRetryConnection][WaitAcceptFinish] background thread stopped! may some error happened");
     457            1 :             return HCCL_E_INTERNAL;
     458              :         }
     459              : 
     460     14685392 :         if (acceptFinished_) {
     461            4 :             HCCL_INFO("[OpRetryConnection][WaitAcceptFinish] wait background thread accept finished");
     462            4 :             return HCCL_SUCCESS;
     463              :         }
     464              : 
     465     14685388 :         if ((std::chrono::steady_clock::now() - startTime) > timeout) {
     466            0 :             HCCL_ERROR("[OpRetryConnection][WaitAcceptFinish] wait accept timeout! timeout[%d s]",
     467              :                 GetExternalInputHcclLinkTimeOut());
     468            0 :             return HCCL_E_TIMEOUT;
     469              :         }
     470              :     }
     471              : 
     472              :     HCCL_ERROR("[OpRetryConnection][WaitAcceptFinish] code should not execute in there");
     473              :     return HCCL_E_INTERNAL;
     474              : }
     475              : 
     476            5 : HcclResult OpRetryConnection::RecvMetaInfo(std::shared_ptr<HcclSocket> &peerSocket)
     477              : {
     478            5 :     u32 peerRankId = INVALID_UINT;
     479            5 :     auto ret = peerSocket->Recv(&peerRankId, sizeof(peerRankId));
     480            5 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     481              :         HCCL_ERROR("[OpRetryConnection][RecvMetaInfo] Recv peer meta info failed. ret [%d]", ret), ret);
     482              : 
     483            5 :     CHK_PRT_RET(peerRankId >= rankSize_,
     484              :         HCCL_ERROR("[OpRetryConnection][RecvMetaInfo] Recv peer meta info invalid peerRankId [%u]. rankSize_[%u]",
     485              :         peerRankId, rankSize_), HCCL_E_INTERNAL);
     486              : 
     487            5 :     if (connectionSockets_.find(peerRankId) != connectionSockets_.end()) {
     488            0 :         HCCL_ERROR("[OpRetryConnection][RecvMetaInfo] Recv same rankId [%u]", peerRankId);
     489            0 :         return HCCL_E_INTERNAL;
     490              :     }
     491              : 
     492            5 :     connectionSockets_.insert({peerRankId, peerSocket});
     493            5 :     HCCL_INFO("[OpRetryConnection][RecvMetaInfo] Recv peer rankId [%u]. rankSize_[%u] success", peerRankId, rankSize_);
     494            5 :     return HCCL_SUCCESS;
     495              : }
     496              : 
     497              : /* 这里我们使用Server与Client侧约定好的rankSize信息作为Server侧的ACK报文 */
     498            5 : HcclResult OpRetryConnection::SendAckInfo(std::shared_ptr<HcclSocket> &peerSocket)
     499              : {
     500            5 :     auto ret = peerSocket->Send(&rankSize_, sizeof(rankSize_));
     501            5 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     502              :         HCCL_ERROR("[OpRetryConnection][SendAckInfo] Send peer meta ack failed, ret %d", ret), ret);
     503              : 
     504            5 :     HCCL_INFO("[OpRetryConnection][SendAckInfo] rank [%u] send ack [%u] success", rankId_, rankSize_);
     505            5 :     return HCCL_SUCCESS;
     506              : }
     507              : 
     508            7 : void OpRetryConnection::RunAccept()
     509              : {
     510            7 :     SetThreadName("Hccl_RetryConn");
     511              : 
     512              :     /* 这里我们跟所有Common进程建链,包括自己 */
     513            7 :     if (Accept() != HCCL_SUCCESS) {
     514            2 :         HCCL_ERROR("[OpRetryConnection][Run] Accept failed, serverIp_[%s] serverPort_[%u]", serverIp_.GetReadableIP(), serverPort_);
     515            2 :         backgroudThreadStop_ = true;
     516            2 :         return;
     517              :     }
     518              : 
     519              :     /* 这里停止listen,是因为后续不再接收新的建链,同时也能够释放该端口,让后续通信域使用 */
     520            5 :     if (StopListen() != HCCL_SUCCESS) {
     521            0 :         HCCL_ERROR("[OpRetryConnection][Run] Stop listen failed, serverIp_[%s] serverPort_[%u]", serverIp_.GetReadableIP(), serverPort_);
     522            0 :         backgroudThreadStop_ = true;
     523            0 :         return;
     524              :     }
     525              : 
     526            5 :     acceptFinished_ = true;
     527            5 :     HCCL_INFO("[OpRetryConnection][Run] Accept all client success");
     528              : }
     529              : 
     530            6 : HcclResult OpRetryConnection::Connect()
     531              : {
     532              :     // 因为Connect可能会被多次调用,因此clientNetCtx不需要多次创建
     533            6 :     if (clientNetCtx_ == nullptr) {
     534            5 :         CHK_RET(HcclNetOpenDev(&clientNetCtx_, NicType::HOST_NIC_TYPE, devicePhysicID_, deviceLogicalID_, localIp_));
     535            5 :         CHK_PTR_NULL(clientNetCtx_);
     536              :     }
     537              : 
     538              :     // 因为Connect可能会被多次调用,因此如果socket已经存在则直接关闭,并创建新的
     539            6 :     if (socket_ != nullptr) {
     540            1 :         socket_->Close();
     541            1 :         socket_ = nullptr;
     542              :     }
     543              : 
     544            6 :     auto tag = GetTag();
     545            6 :     EXCEPTION_CATCH((socket_ = std::make_shared<HcclSocket>(tag,
     546              :         clientNetCtx_, serverIp_, serverPort_, HcclSocketRole::SOCKET_ROLE_CLIENT)), return HCCL_E_PTR);
     547            6 :     CHK_SMART_PTR_NULL(socket_);
     548            6 :     CHK_RET(socket_->Init());
     549            6 :     CHK_RET(socket_->Connect());
     550              : 
     551            6 :     auto startTime = std::chrono::steady_clock::now();
     552            6 :     auto timeout = std::chrono::seconds(GetExternalInputHcclLinkTimeOut());
     553              :     while (true) {
     554           16 :         if ((std::chrono::steady_clock::now() - startTime) >= timeout) {
     555            1 :             HCCL_ERROR("[OpRetryConnection][Connect] Get socket timeout! timeout [%ld s]", timeout);
     556            1 :             return HCCL_E_TIMEOUT;
     557              :         }
     558              : 
     559           15 :         auto status = socket_->GetStatus();
     560           15 :         if (status == HcclSocketStatus::SOCKET_CONNECTING) {
     561           10 :             SaluSleep(ONE_MILLISECOND_OF_USLEEP);
     562           10 :             continue;
     563            5 :         } else if (status != HcclSocketStatus::SOCKET_OK) {
     564            0 :             HCCL_ERROR("[OpRetryConnection][Connect] Get socket failed, ret [%d]", status);
     565            0 :             return HCCL_E_TCP_CONNECT;
     566              :         } else {
     567            5 :             HCCL_INFO("[OpRetryConnection][Connect] Get socket success with server [%s] port [%u]",
     568              :                 serverIp_.GetReadableIP(), serverPort_);
     569            5 :             break;
     570              :         }
     571           10 :     }
     572              : 
     573            5 :     CHK_RET(SendMetaInfo());
     574            5 :     CHK_RET(RecvAckInfo());
     575            4 :     return HCCL_SUCCESS;
     576            6 : }
     577              : 
     578              : /* 目前meta信息主要是rankId */
     579            5 : HcclResult OpRetryConnection::SendMetaInfo()
     580              : {
     581            5 :     auto ret = socket_->Send(&rankId_, sizeof(rankId_));
     582            5 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     583              :         HCCL_WARNING("[OpRetryConnection][SendMetaInfo] Send peer meta info failed, ret %d", ret),
     584              :         HCCL_E_AGAIN);
     585              : 
     586            5 :     HCCL_INFO("[OpRetryConnection][SendMetaInfo] rank [%u] send meta info success", rankId_);
     587            5 :     return HCCL_SUCCESS;
     588              : }
     589              : 
     590            4 : HcclResult OpRetryConnection::RecvAckInfo()
     591              : {
     592            4 :     u32 ackRankSize = 0;
     593            4 :     auto ret = socket_->Recv(&ackRankSize, sizeof(ackRankSize));
     594            4 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     595              :         HCCL_WARNING("[OpRetryConnection][RecvAckTag] Recv peer ack info failed. ret [%d]", ret),
     596              :         HCCL_E_AGAIN);
     597              : 
     598            4 :     if (ackRankSize != rankSize_) {
     599            0 :         HCCL_ERROR("[OpRetryConnection][RecvAckTag] Recv unmatched ack [%u] expect [%u]", ackRankSize, rankSize_);
     600            0 :         return HCCL_E_INTERNAL;
     601              :     }
     602              : 
     603            4 :     HCCL_INFO("[OpRetryConnection][RecvAckTag] Recv ack [%u] success", ackRankSize);
     604            4 :     return HCCL_SUCCESS;
     605              : }
     606              : 
     607            1 : HcclResult OpRetryConnection::GetHostSocketWhiteList()
     608              : {
     609            1 :     auto whiteListFile = GetExternalInputHcclWhiteListFile();
     610            1 :     CHK_PRT_RET((whiteListFile.length() == 0),
     611              :         HCCL_ERROR("[OpRetryConnection][GetHostSocketWhitelist]environment variable HCCL_WHITELIST_FILE is not set or not exist"), HCCL_E_PARA);
     612              : 
     613            1 :     HcclResult ret = LoadHostWhiteList(whiteListFile);
     614            1 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     615              :         HCCL_ERROR("[OpRetryConnection][GetHostSocketWhitelist]hccl whitelist load config file[%s] failed. ret[%u].",
     616              :             whiteListFile.c_str(), ret), ret);
     617              : 
     618            1 :     CHK_PRT_RET(whitelist_.empty(), HCCL_ERROR("[OpRetryConnection][GetHostSocketWhitelist]whitelist file[%s] have no valid host ip.",
     619              :         whiteListFile.c_str()), HCCL_E_UNAVAIL);
     620              : 
     621            1 :     HCCL_INFO("[OpRetry][GetHostSocketWhiteList]Get host socket whitelist success. there are %zu host ip in the whitelist.",
     622              :         whitelist_.size());
     623            1 :     return HCCL_SUCCESS;
     624            1 : }
     625              : 
     626            1 : HcclResult OpRetryConnection::AddListenSocketWhiteList()
     627              : {
     628            1 :     wlistInfosVec_.clear();
     629            2 :     for (auto ip : whitelist_) {
     630              :         SocketWlistInfo wlistInfo;
     631            1 :         wlistInfo.connLimit = HOST_SOCKET_CONN_LIMIT;
     632            1 :         wlistInfo.remoteIp.addr = ip.GetBinaryAddress().addr;
     633            1 :         wlistInfo.remoteIp.addr6 = ip.GetBinaryAddress().addr6;
     634            1 :         std::string tag = GetTag();
     635            1 :         s32 sRet = memcpy_s(&wlistInfo.tag[0], sizeof(wlistInfo.tag), tag.c_str(), tag.size() + 1);
     636            1 :         if (sRet != EOK) {
     637            0 :             HCCL_ERROR("[OpRetryConnection][AddListenSocketWhiteList]memory copy failed. errorno[%d]", sRet);
     638            0 :             return HCCL_E_MEMORY;
     639              :         }
     640            1 :         wlistInfosVec_.push_back(wlistInfo);
     641            1 :         HCCL_INFO("[OpRetryConnection][AddListenSocketWhiteList] add white ip %s", ip.GetReadableIP());
     642            1 :     }
     643              : 
     644            1 :     CHK_RET(listenSocket_->AddWhiteList(wlistInfosVec_));
     645              : 
     646            1 :     HCCL_INFO("[OpRetryConnection][AddListenSocketWhiteList] add socket white list success. total: %zu", whitelist_.size());
     647            1 :     return HCCL_SUCCESS;
     648              : }
     649              : 
     650            0 : u32 OpRetryConnection::GetServerPort()
     651              : {
     652            0 :     u32 serverPort = HCCL_INVALID_PORT;
     653            0 :     if (GetExternalInputHcclIfBasePort() == HCCL_INVALID_PORT) {
     654            0 :         serverPort = HOST_CONTROL_BASE_PORT;
     655              :     } else {
     656            0 :         serverPort = GetExternalInputHcclIfBasePort();
     657              :     }
     658              : 
     659            0 :     return serverPort;
     660              : }
     661              : }
        

Generated by: LCOV version 2.0-1