LCOV - code coverage report
Current view: top level - legacy/ascend910/framework/cluster_maintenance/recovery/operator_retry - opretry_agent.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 22.8 % 685 156
Test Date: 2026-08-18 17:47:01 Functions: 36.0 % 25 9

            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 <chrono>
      12              : #include "externalinput_pub.h"
      13              : #include "sal_pub.h"
      14              : #include "heartbeat.h"
      15              : #include "comm_configer.h"
      16              : #include "opretry_agent.h"
      17              : 
      18              : namespace hccl {
      19            5 : HcclResult CreateOpRetryAgentByState(RetryState state, RetryContext* retryCtx)
      20              : {
      21            5 :     HCCL_INFO("[OpRetry][Agent]CreateOpRetryAgentByState state[%s]", GetReadableState(state));
      22            5 :     std::shared_ptr<OpRetryBase> retryPtr = nullptr;
      23            5 :     switch (state) {
      24            2 :         case RETRY_STATE_AGENT_RUNNING: {
      25            2 :             EXCEPTION_CATCH(retryPtr = std::make_shared<OpRetryAgentRunning>(), return HCCL_E_PTR);
      26            2 :             break;
      27              :         }
      28            0 :         case RETRY_STATE_AGENT_RETRY_FAIL: {
      29            0 :             EXCEPTION_CATCH(retryPtr = std::make_shared<OpRetryAgentRetryFail>(), return HCCL_E_PTR);
      30            0 :             break;
      31              :         }
      32            1 :         case RETRY_STATE_RESP_AICPU_ERR:
      33              :         case RETRY_STATE_RESP_AICPU_STOPED:
      34              :         case RETRY_STATE_RESP_STREAM_STOPED:
      35              :         case RETRY_STATE_RESP_STREAM_CLEARED:
      36              :         case RETRY_STATE_RESP_LINK_CHANGED:
      37              :         case RETRY_STATE_RESP_STOP_TRANSPORT:
      38              :         case RETRY_STATE_RESP_NOTIFY_RESETED:
      39              :         case RETRY_STATE_RESP_RESUME_TRANSPORT:
      40              :         case RETRY_STATE_RESP_CHECK_INFO:
      41              :         case RETRY_STATE_RESP_AICPU_RETRYEND:
      42              :         case RETRY_STATE_RESP_RUNNING_ERR: {
      43            1 :             EXCEPTION_CATCH(retryPtr = std::make_shared<OpRetryAgentResponse>(), return HCCL_E_PTR);
      44            1 :             break;
      45              :         }
      46            0 :         case RETRY_STATE_RESP_LINK_CHECKED: {
      47            0 :             EXCEPTION_CATCH(retryPtr = std::make_shared<OpRetryAgentResponseLinkInfo>(), return HCCL_E_PTR);
      48            0 :             break;
      49              :         }
      50            0 :         case RETRY_STATE_WAIT_CHANGE_LINK_INFO: {
      51            0 :             EXCEPTION_CATCH(retryPtr = std::make_shared<OpRetryAgentWaitChangeLinkInfo>(), return HCCL_E_PTR);
      52            0 :             break;
      53              :         }
      54            0 :         case RETRY_STATE_WAIT_CMD_STOP_AICPU:
      55              :         case RETRY_STATE_WAIT_CMD_STOP_STREAM:
      56              :         case RETRY_STATE_WAIT_CMD_CLEAR_STREAM:
      57              :         case RETRY_STATE_WAIT_CMD_STOP_TRANSPORT:
      58              :         case RETRY_STATE_WAIT_CMD_RESET_NOTIFY:
      59              :         case RETRY_STATE_WAIT_CMD_CHECK_LINK:
      60              :         case RETRY_STATE_WAIT_CMD_RESUME_TRANSPORT:
      61              :         case RETRY_STATE_WAIT_CMD_CHECK:
      62              :         case RETRY_STATE_WAIT_CMD_CAN_RETRY:
      63              :         case RETRY_STATE_WAIT_CMD_RETRY_FAIL: {
      64            0 :             EXCEPTION_CATCH(retryPtr = std::make_shared<OpRetryAgentWaitCmd>(), return HCCL_E_PTR);
      65            0 :             break;
      66              :         }
      67            0 :         case RETRY_STATE_POLL_AICPU_STOPED:
      68              :         case RETRY_STATE_POLL_AICPU_CHANGED:
      69              :         case RETRY_STATE_POLL_AICPU_RETRYEND:
      70              :         case RETRY_STATE_POLL_STREAM_STOPED: {
      71            0 :             EXCEPTION_CATCH(retryPtr = std::make_shared<OpRetryAgentPollAicpuStop>(), return HCCL_E_PTR);
      72            0 :             break;
      73              :         }
      74              :         // 发送主动借轨信息
      75            1 :         case RETRY_STATE_SEND_SWITCH_INFO:
      76            1 :             EXCEPTION_CATCH(retryPtr = std::make_shared<SwitchNicAgentSendSwitchInfo>(), return HCCL_E_PTR);
      77            1 :             break;
      78              :         // 等待server RetryCommand命令
      79            1 :         case RETRY_STATE_WAIT_CMD_SEND_AICPU:
      80            1 :             EXCEPTION_CATCH(retryPtr = std::make_shared<SwitchNicAgentWaitCmd>(), return HCCL_E_PTR);
      81            1 :             break;
      82              :         // Resume 过程中检查网口和链路状态(接收来自Server的命令,检查网口和链路状态,将信息回复发送给Server)
      83            0 :         case RETRY_RESUME_STATE_AGENT_CHECK_LINK:
      84            0 :             EXCEPTION_CATCH(retryPtr = std::make_shared<ResumeAgentCheckLink>(), return HCCL_E_PTR);
      85            0 :             break;
      86              :         // Resume 过程中接收Server借轨命令,下发给Aicpu背景线程,借轨完成通知Server
      87            0 :         case RETRY_RESUME_STATE_AGENT_CHANGE_LINK:
      88            0 :             EXCEPTION_CATCH(retryPtr = std::make_shared<ResumeAgentChangeLink>(), return HCCL_E_PTR);
      89            0 :             break;
      90            0 :         default: {
      91            0 :             HCCL_ERROR(
      92              :                 "[OpRetry][Agent]CreateOpRetryAgentByState failed, state[%s] is invalid", GetReadableState(state));
      93            0 :             return HCCL_E_NOT_SUPPORT;
      94              :         }
      95              :     }
      96            5 :     retryCtx->SetRetryState(state, retryPtr);
      97            5 :     return HCCL_SUCCESS;
      98            5 : }
      99              : 
     100            0 : HcclResult OpRetryAgentBase::ProcessError(RetryContext* retryCtx)
     101              : {
     102            0 :     HCCL_ERROR(
     103              :         "[%s]OpRetryAgent run fail, rankId[%u], state[%s], IpInfo[%s]", __func__, retryCtx->rankId_,
     104              :         retryCtx->GetReadableCtxState(), retryCtx->GetDfxIpInfo());
     105              :     // 状态切换至RETRY_STATE_RESP_RUNNING_ERR(上报Server)
     106            0 :     CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_RESP_RUNNING_ERR, retryCtx));
     107            0 :     return HCCL_SUCCESS;
     108              : }
     109              : 
     110            8 : OpRetryAgentRunning::OpRetryAgentRunning()
     111              : {
     112            8 :     lastRecvCmdTime_ = std::chrono::steady_clock::now();
     113            8 :     lastPollAicpuTime_ = lastRecvCmdTime_;
     114            8 :     pollTimeout_ = std::chrono::seconds(OP_RETRY_POLL_AICPU_ERROR_INTERVAL); // 轮询aicpu间隔
     115            8 :     keepTimeout_ = std::chrono::seconds(OP_RETRY_KEEP_INTERVAL);             // 发送保活数据间隔
     116              : 
     117            8 :     lastPollRcTime_ = lastRecvCmdTime_;
     118            8 :     lastKeepTime_ = lastRecvCmdTime_;
     119            8 :     pollRcTimeout_ = std::chrono::seconds(OP_RETRY_POLL_RDMA_ERROR_INTERVAL); // 轮询rdma cqe间隔
     120            8 : }
     121              : 
     122              : // RETRY_STATE_AGENT_RUNNING
     123            1 : HcclResult OpRetryAgentRunning::ProcessEvent(RetryContext* retryCtx)
     124              : {
     125            1 :     HcclResult ret = HCCL_SUCCESS;
     126            1 :     std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
     127              : 
     128              :     // 定期轮询aicpu状态
     129            1 :     const auto pollTime = std::chrono::duration_cast<std::chrono::seconds>(curTime - lastPollAicpuTime_);
     130            1 :     if (pollTime > pollTimeout_) {
     131            0 :         if (retryCtx->isEnableSdmaRetry_) {
     132            0 :             RetryState nextState = RETRY_STATE_RESERVED;
     133            0 :             CHK_RET(ParseKfcErr(retryCtx, nextState));
     134            0 :             if (nextState != RETRY_STATE_RESERVED) {
     135            0 :                 CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_RESP_AICPU_ERR, retryCtx));
     136            0 :                 return HCCL_SUCCESS;
     137              :             }
     138              :         }
     139            0 :         lastPollAicpuTime_ = curTime;
     140              :     }
     141              : 
     142              :     // 定期轮询 Rdma Cqe 状态
     143            1 :     const auto pollRcTime = std::chrono::duration_cast<std::chrono::seconds>(curTime - lastPollRcTime_);
     144            1 :     if (pollRcTime > pollRcTimeout_) {
     145            0 :         HCCL_DEBUG("[OpRetry][Agent] OpRetryAgentRunning poll rdma err");
     146            0 :         if (retryCtx->isEnableBackupLink_) {
     147            0 :             RetryState nextState = RETRY_STATE_RESERVED;
     148              :             // 遍历 RDMA CQE Error 状态
     149            0 :             CHK_RET(ParseRdmaErr(retryCtx, nextState));
     150            0 :             if (nextState != RETRY_STATE_RESERVED) {
     151            0 :                 CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
     152            0 :                 return HCCL_SUCCESS;
     153              :             }
     154              :         }
     155            0 :         lastPollRcTime_ = curTime;
     156              :     }
     157              : 
     158              :     // OpRetryAgent Running状态下,读取到KfcStatus:kPlanSwitch或kSwitchError,切换状态机状态。
     159            1 :     const auto activeTime = std::chrono::duration_cast<std::chrono::seconds>(curTime - lastPollAicpuTime_);
     160            1 :     KfcExecStatus& opInfo = retryCtx->localRetryInfo_.opInfo;
     161            1 :     CHK_RET(GetOpExecInfo(retryCtx->GetD2hPtr(), opInfo));
     162            1 :     const KfcStatus& aicpuState = opInfo.execStatus.kfcStatus;
     163            1 :     if (aicpuState == KfcStatus::kPlanSwitch || aicpuState == KfcStatus::kSwitchError) {
     164            1 :         CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_SEND_SWITCH_INFO, retryCtx));
     165            1 :         return HCCL_SUCCESS;
     166              :     }
     167              : 
     168              :     // 查看是否收到server的command
     169            0 :     RetryCommandInfo commandinfo;
     170            0 :     ret = WaitCommandWithOpId(retryCtx->agentSocket_, commandinfo);
     171            0 :     if (ret == HCCL_SUCCESS) {
     172            0 :         if (commandinfo.command == RETRY_CMD_STOP_AICPU) { // 接收到有效command信息
     173            0 :             HCCL_RUN_INFO(
     174              :                 "[OpRetry][Agent]OpRetryAgentRunning recv command[%s] success, "
     175              :                 "tag[%s], index[%u], srcRank[%u], detRank[%u], isSendRecv[%d], streamId[%u]",
     176              :                 GetReadableCmd(commandinfo.command), commandinfo.opId.tag, commandinfo.opId.index,
     177              :                 commandinfo.opId.srcRank, commandinfo.opId.detRank, commandinfo.opId.isSendRecv,
     178              :                 commandinfo.opId.streamId);
     179            0 :             CHK_RET(SetOpExecCmdWithOpId(retryCtx->GetH2dPtr(), KfcCommand::kStopLaunch, commandinfo.opId));
     180            0 :             retryCtx->curFaultOpId = commandinfo.opId;
     181            0 :             CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_POLL_AICPU_STOPED, retryCtx));
     182            0 :             return HCCL_SUCCESS;
     183            0 :         } else if (commandinfo.command == RETRY_CMD_RUNNING) {
     184              :             // 接收到RUN命令时发送保活数据
     185            0 :             const auto keepTime = std::chrono::duration_cast<std::chrono::seconds>(curTime - lastKeepTime_);
     186            0 :             if (keepTime > keepTimeout_) {
     187            0 :                 CHK_RET(GetRetryInfo(retryCtx, retryCtx->localRetryInfo_));
     188            0 :                 HcclResult ret = IssueResponse(retryCtx->agentSocket_, retryCtx->localRetryInfo_);
     189            0 :                 if (ret != HCCL_SUCCESS) { // 发送保活数据失败, 打印warning
     190            0 :                     HCCL_WARNING("[OpRetry][Agent]OpRetryAgentRunning issue response fail, ret[%d]", ret);
     191              :                 }
     192            0 :                 HCCL_RUN_INFO("[OpRetry][Agent]upload tag[%s]", retryCtx->localRetryInfo_.opInfo.opId.tag);
     193            0 :                 lastKeepTime_ = curTime;
     194              :             }
     195              :         }
     196              :     }
     197              : 
     198              :     // 轮询间隔
     199            0 :     SaluSleep(OP_RETRY_RUNNING_POLL_INTERVAL);
     200            0 :     return HCCL_SUCCESS;
     201              : }
     202              : 
     203            0 : HcclResult OpRetryAgentRunning::ParseRdmaErr(RetryContext* retryCtx, RetryState& nextState)
     204              : {
     205            0 :     nextState = RETRY_STATE_RESERVED;
     206            0 :     CHK_RET(GetRetryInfo(retryCtx, retryCtx->localRetryInfo_));
     207            0 :     auto& opId = retryCtx->localRetryInfo_.opInfo.opId;
     208              : 
     209              :     // 先判断是否有遗留的cqe err需要处理,没有再去心跳获取
     210            0 :     bool isBatchSendRecv = (opId.opType == HcclCMDType::HCCL_CMD_BATCH_SEND_RECV);
     211            0 :     bool isSendRecv = (opId.opType == HcclCMDType::HCCL_CMD_SEND) || (opId.opType == HcclCMDType::HCCL_CMD_RECEIVE);
     212            0 :     bool IsSupportRdmaRetry = false;
     213            0 :     if (isBatchSendRecv) {
     214            0 :         if (retryCtx->isBSRRdmaSendError_) {
     215            0 :             CHK_RET(GetBsrOpId(retryCtx, HcclSendRecvType::HCCL_SEND));
     216            0 :             nextState = RETRY_STATE_RESP_AICPU_ERR;
     217            0 :             retryCtx->localRetryInfo_.opInfo.execStatus.kfcError = KfcError::kRdma;
     218            0 :             retryCtx->localRetryInfo_.opInfo.execStatus.kfcStatus = KfcStatus::kStoplaunch;
     219            0 :             HCCL_RUN_INFO(
     220              :                 "[OpRetry][Agent]batchsendrecv rdma send op need retry, tag[%s] index[%u]", opId.tag, opId.index);
     221            0 :             return HCCL_SUCCESS;
     222              :         }
     223            0 :         if (retryCtx->isBSRRdmaRecvError_) {
     224            0 :             CHK_RET(GetBsrOpId(retryCtx, HcclSendRecvType::HCCL_RECV));
     225            0 :             nextState = RETRY_STATE_RESP_AICPU_ERR;
     226            0 :             retryCtx->localRetryInfo_.opInfo.execStatus.kfcError = KfcError::kRdma;
     227            0 :             retryCtx->localRetryInfo_.opInfo.execStatus.kfcStatus = KfcStatus::kStoplaunch;
     228            0 :             HCCL_RUN_INFO(
     229              :                 "[OpRetry][Agent]batchsendrecv rdma recv op need retry, tag[%s] index[%u]", opId.tag, opId.index);
     230            0 :             return HCCL_SUCCESS;
     231              :         }
     232              :     }
     233              :     // 1. 获取 Rdma Err 信息
     234            0 :     std::set<std::tuple<u32, u32, u32>> infoSet;
     235            0 :     Heartbeat::GetInstance(retryCtx->deviceLogicId_).GetQpnErr(retryCtx->group_, infoSet);
     236            0 :     bool isExistQPErr = (infoSet.size() > 0);
     237            0 :     if (!isExistQPErr) {
     238            0 :         return HCCL_SUCCESS;
     239              :     }
     240            0 :     if (isBatchSendRecv) {
     241            0 :         for (auto& info : infoSet) {
     242            0 :             u32 qpn = std::get<2>(info);
     243            0 :             u32 qpnStatus = std::get<1>(info);
     244            0 :             if (qpn == opId.bsrInfo[HCCL_SEND].tpQpn && qpnStatus == RDMA_CQE_ERR_STATUS) { // SendQpn  QpnStatus
     245            0 :                 retryCtx->isBSRRdmaSendError_ = true;
     246            0 :                 CHK_RET(SetBsrOpId(retryCtx, HcclSendRecvType::HCCL_SEND));
     247              :             }
     248            0 :             if (qpn == opId.bsrInfo[HCCL_RECV].tpQpn && qpnStatus == RDMA_CQE_ERR_STATUS) { // RecvQpn QpnStatus
     249            0 :                 retryCtx->isBSRRdmaRecvError_ = true;
     250            0 :                 CHK_RET(SetBsrOpId(retryCtx, HcclSendRecvType::HCCL_RECV));
     251              :             }
     252            0 :             HCCL_RUN_INFO(
     253              :                 "[OpRetry][Agent]pollcqeErr, ErrQpn [%u] SendQpn [%u] RecvQpn [%u]", qpn, opId.bsrInfo[HCCL_SEND].tpQpn,
     254              :                 opId.bsrInfo[HCCL_RECV].tpQpn);
     255              :         }
     256              :         // 处理bsr重执行,若send/recv同时报错,优先处理send报错,重执行成功后再处理recv报错
     257              :         // 故障是从host侧识别出来的,然后上报故障的时候需要将aicpu侧上报的batchsendrecv刷成sendrecv
     258            0 :         if (retryCtx->isBSRRdmaSendError_) {
     259            0 :             opId.index = opId.bsrInfo[HCCL_SEND].index;
     260            0 :             CHK_SAFETY_FUNC_RET(memset_s(opId.tag, sizeof(opId.tag), 0, sizeof(opId.tag)));
     261            0 :             CHK_SAFETY_FUNC_RET(memcpy_s(
     262              :                 opId.tag, sizeof(opId.tag), opId.bsrInfo[HCCL_SEND].bsrTag, sizeof(opId.bsrInfo[HCCL_SEND].bsrTag)));
     263            0 :             opId.srcRank = opId.bsrInfo[HCCL_SEND].srcRank;
     264            0 :             opId.detRank = opId.bsrInfo[HCCL_SEND].detRank;
     265            0 :             opId.streamId = opId.bsrInfo[HCCL_SEND].streamId;
     266            0 :             opId.isSendRecv = true;
     267            0 :             opId.opType = HcclCMDType::HCCL_CMD_BATCH_SEND_RECV;
     268            0 :             IsSupportRdmaRetry = true;
     269            0 :         } else if (retryCtx->isBSRRdmaRecvError_) {
     270            0 :             opId.index = opId.bsrInfo[HCCL_RECV].index;
     271            0 :             CHK_SAFETY_FUNC_RET(memset_s(opId.tag, sizeof(opId.tag), 0, sizeof(opId.tag)));
     272            0 :             CHK_SAFETY_FUNC_RET(memcpy_s(
     273              :                 opId.tag, sizeof(opId.tag), opId.bsrInfo[HCCL_RECV].bsrTag, sizeof(opId.bsrInfo[HCCL_RECV].bsrTag)));
     274            0 :             opId.srcRank = opId.bsrInfo[HCCL_RECV].srcRank;
     275            0 :             opId.detRank = opId.bsrInfo[HCCL_RECV].detRank;
     276            0 :             opId.streamId = opId.bsrInfo[HCCL_RECV].streamId;
     277            0 :             opId.isSendRecv = true;
     278            0 :             opId.opType = HcclCMDType::HCCL_CMD_BATCH_SEND_RECV;
     279            0 :             IsSupportRdmaRetry = true;
     280              :         }
     281            0 :     } else if (isSendRecv) {
     282            0 :         auto detRank = retryCtx->localRetryInfo_.rankId == retryCtx->localRetryInfo_.opInfo.opId.detRank ?
     283              :                            retryCtx->localRetryInfo_.opInfo.opId.srcRank :
     284              :                            retryCtx->localRetryInfo_.opInfo.opId.detRank;
     285            0 :         HCCL_INFO("[OpRetry][Agent][Rdma]now in isSendRecv branch (isSendRecv[%d])", isSendRecv);
     286            0 :         bool isFindDstRank = false;
     287            0 :         for (auto& info : infoSet) {
     288            0 :             u32 remoteRank = std::get<0>(info);
     289            0 :             u32 qpnStatus = std::get<1>(info);
     290            0 :             if (remoteRank == detRank) {
     291            0 :                 isFindDstRank = true;
     292            0 :                 if (qpnStatus == RDMA_CQE_ERR_STATUS) {
     293            0 :                     HCCL_INFO("[OpRetry][Agent][Rdma]SendRecv can support Rdma Retry");
     294            0 :                     IsSupportRdmaRetry = true;
     295              :                 }
     296            0 :                 break;
     297              :             }
     298              :         }
     299            0 :         if (!isFindDstRank) {
     300            0 :             HCCL_ERROR("[OpRetry][Agent] dstRank[%u] is not in infolist, do nothing", detRank);
     301            0 :             nextState = RETRY_STATE_AGENT_RETRY_FAIL;
     302              :         }
     303            0 :         HCCL_INFO("[OpRetry][Agent][Rdma]SendRecv link IsSupportRdmaRetry[%d]", IsSupportRdmaRetry);
     304              :     } else {
     305              :         // 非点对点通信分支
     306            0 :         HCCL_INFO("[OpRetry][Agent][Rdma]now in Full link branch (isSendRecv[%d])", isSendRecv);
     307            0 :         for (auto& info : infoSet) {
     308            0 :             u32 remoteRank = std::get<0>(info);
     309            0 :             u32 qpnStatus = std::get<1>(info);
     310            0 :             HCCL_INFO("remoteRank = [%u] , status = [%u]", remoteRank, qpnStatus);
     311            0 :             IsSupportRdmaRetry = true; // 默认设置为支持Rdma重执行
     312            0 :             if (qpnStatus != RDMA_CQE_ERR_STATUS) {
     313            0 :                 IsSupportRdmaRetry = false;
     314            0 :                 nextState = RETRY_STATE_AGENT_RETRY_FAIL;
     315            0 :                 HCCL_ERROR("[OpRetry][Agent] remoteRank[%u] status[%u] is not 12", remoteRank, qpnStatus);
     316            0 :                 break;
     317              :             }
     318              :         }
     319            0 :         HCCL_INFO("[OpRetry][Agent][Rdma]Full link IsSupportRdmaRetry[%d]", IsSupportRdmaRetry);
     320              :     }
     321            0 :     if (IsSupportRdmaRetry) {
     322            0 :         nextState = RETRY_STATE_RESP_AICPU_ERR;
     323            0 :         retryCtx->localRetryInfo_.opInfo.execStatus.kfcError = KfcError::kRdma;
     324            0 :         retryCtx->localRetryInfo_.opInfo.execStatus.kfcStatus = KfcStatus::kStoplaunch;
     325              :     }
     326            0 :     HCCL_INFO("[OpRetry][Agent][Rdma]nextState is [%s]", GetReadableState(nextState));
     327            0 :     return HCCL_SUCCESS;
     328            0 : }
     329              : 
     330            0 : HcclResult OpRetryAgentRunning::ParseKfcErr(RetryContext* retryCtx, RetryState& nextState)
     331              : {
     332            0 :     nextState = RETRY_STATE_RESERVED;
     333              :     // 记录上一次轮询获取的错误码, 避免日志刷屏
     334            0 :     KfcError lastError = retryCtx->localRetryInfo_.opInfo.execStatus.kfcError;
     335            0 :     CHK_RET(GetRetryInfo(retryCtx, retryCtx->localRetryInfo_));
     336            0 :     KfcError kfcError = retryCtx->localRetryInfo_.opInfo.execStatus.kfcError;
     337            0 :     uint32_t retryCnt = retryCtx->localRetryInfo_.opInfo.execStatus.retryInfo.retryCount;
     338            0 :     switch (kfcError) {
     339            0 :         case KfcError::kNone: {
     340            0 :             break;
     341              :         }
     342            0 :         case KfcError::kSdma: {
     343            0 :             HCCL_RUN_INFO("[OpRetry][Agent]Get ErrorCode[%d] rertryCnt[%u]", kfcError, retryCnt);
     344            0 :             nextState = RETRY_STATE_RESP_AICPU_ERR;
     345            0 :             break;
     346              :         }
     347            0 :         default: {
     348            0 :             if (lastError != kfcError) {
     349            0 :                 HCCL_RUN_INFO("[OpRetry][Agent]KfcError[%d] is not support, do nothing", kfcError);
     350              :             }
     351            0 :             break;
     352              :         }
     353              :     }
     354            0 :     return HCCL_SUCCESS;
     355              : }
     356              : 
     357              : // 向server状态机发送信息
     358            0 : HcclResult OpRetryAgentResponse::ProcessEvent(RetryContext* retryCtx)
     359              : {
     360              :     // 获取预期的下一个状态
     361            0 :     RetryState nextState = RETRY_STATE_RESERVED;
     362            0 :     auto it = RETRY_AGENT_RESP_STATE_LABEL.find(retryCtx->localRetryInfo_.retryState);
     363            0 :     CHK_PRT_RET(
     364              :         it == RETRY_AGENT_RESP_STATE_LABEL.end(),
     365              :         HCCL_ERROR(
     366              :             "[OpRetry][Agent]OpRetryAgentResponse fail, state[%s] is not in RETRY_AGENT_RESP_STATE_LABEL",
     367              :             GetReadableState(retryCtx->localRetryInfo_.retryState)),
     368              :         HCCL_E_INTERNAL);
     369            0 :     nextState = it->second;
     370            0 :     auto& opInfo = retryCtx->localRetryInfo_.opInfo;
     371            0 :     HCCL_RUN_INFO(
     372              :         "[OpRetry][Agent]OpRetryAgentResponse tag[%s], index[%u], srcRank[%u], detRank[%u], isSendRecv[%d],"
     373              :         "opExeState[%d], errorCode[%d], retryCount[%u], streamId[%u], isNeedReportOpRetryErr[%d]",
     374              :         opInfo.opId.tag, opInfo.opId.index, opInfo.opId.srcRank, opInfo.opId.detRank, opInfo.opId.isSendRecv,
     375              :         opInfo.execStatus.kfcStatus, opInfo.execStatus.kfcError, opInfo.execStatus.retryInfo.retryCount,
     376              :         opInfo.opId.streamId, retryCtx->localRetryInfo_.isNeedReportOpRetryErr);
     377              : 
     378              :     // 发送数据
     379            0 :     HcclResult ret = IssueResponse(retryCtx->agentSocket_, retryCtx->localRetryInfo_);
     380            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[OpRetry][Agent]OpRetryAgentResponse IssueResponse fail"), ret);
     381            0 :     CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
     382            0 :     return HCCL_SUCCESS;
     383              : }
     384              : 
     385              : // 从server状态机接收命令
     386            0 : HcclResult OpRetryAgentWaitCmd::ProcessEvent(RetryContext* retryCtx)
     387              : {
     388            0 :     RetryState curState = retryCtx->localRetryInfo_.retryState;
     389            0 :     RetryState nextState = RETRY_STATE_RESERVED;
     390            0 :     RetryCommandInfo commandinfo;
     391            0 :     std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
     392            0 :     const u32 timeoutValue = std::max(static_cast<u32>(GetExternalInputHcclLinkTimeOut()), OP_RETRY_SEND_RECV_TIMEOUT)
     393            0 :                              + OP_RETRY_WAIT_AICPU_TIMEOUT;
     394            0 :     const std::chrono::seconds timeout = std::chrono::seconds(timeoutValue);
     395              : 
     396              :     // 接收到命令和当前状态不匹配时, 不做处理, 等待下一个命令, 直到命令正确或者超时
     397              :     while (true) {
     398            0 :         std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
     399            0 :         const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime);
     400            0 :         CHK_PRT_RET(elapsed > timeout, HCCL_ERROR("[OpRetry]WaitCommand timeout"), HCCL_E_TIMEOUT);
     401            0 :         CHK_PRT_RET(
     402              :             retryCtx->isAgentStateWaitResume_,
     403              :             HCCL_RUN_INFO("[OpRetry][Agent]switched state form wait cmd to wait resume"), HCCL_SUCCESS);
     404              : 
     405            0 :         HcclResult ret = WaitCommandWithOpId(retryCtx->agentSocket_, commandinfo);
     406            0 :         if (ret == HCCL_SUCCESS) {
     407            0 :             HCCL_RUN_INFO(
     408              :                 "[OpRetry][Agent]OpRetryAgentGetCmd state[%s] command[%s]"
     409              :                 "tag[%s], index[%u], srcRank[%u], detRank[%u], isSendRecv[%d], streamid[%u]",
     410              :                 GetReadableState(curState), GetReadableCmd(commandinfo.command), commandinfo.opId.tag,
     411              :                 commandinfo.opId.index, commandinfo.opId.srcRank, commandinfo.opId.detRank, commandinfo.opId.isSendRecv,
     412              :                 commandinfo.opId.streamId);
     413            0 :             CHK_PRT(ParseCommandWithOpId(retryCtx, commandinfo, nextState));
     414            0 :             if (nextState != RETRY_STATE_RESERVED) { // 接收到的命令有效
     415            0 :                 break;
     416              :             }
     417              :         }
     418            0 :     }
     419            0 :     CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
     420            0 :     return HCCL_SUCCESS;
     421              : }
     422              : 
     423              : HcclResult
     424            0 : OpRetryAgentWaitCmd::ParseCommandWithOpId(RetryContext* retryCtx, RetryCommandInfo& commandinfo, RetryState& nextState)
     425              : {
     426            0 :     if (!retryCtx->isChangeLinkInfoInit_) {
     427            0 :         CHK_RET(InitChangeLinkInfo(retryCtx));
     428            0 :         retryCtx->isChangeLinkInfoInit_ = true;
     429              :     } else {
     430              :         // 增量建链场景
     431            0 :         CHK_RET(InitChangeLinkInfo(retryCtx, true));
     432              :     }
     433            0 :     RetryState curState = retryCtx->localRetryInfo_.retryState;
     434            0 :     switch (commandinfo.command) {
     435            0 :         case RETRY_CMD_STOP_AICPU:
     436            0 :             if (curState == RETRY_STATE_WAIT_CMD_STOP_AICPU) {
     437            0 :                 CHK_RET(SetOpExecCmdWithOpId(retryCtx->GetH2dPtr(), KfcCommand::kStopLaunch, commandinfo.opId));
     438            0 :                 retryCtx->curFaultOpId = commandinfo.opId;
     439            0 :                 nextState = RETRY_STATE_POLL_AICPU_STOPED;
     440              :             }
     441            0 :             break;
     442            0 :         case RETRY_CMD_STOP_STREAM:
     443            0 :             if (curState == RETRY_STATE_WAIT_CMD_STOP_STREAM) {
     444            0 :                 CHK_RET(ClearStreamWithOpId(
     445              :                     retryCtx->opStreamPtr_, HcclRtStreamClearStep::HCCL_STREAM_STOP, commandinfo.opId,
     446              :                     retryCtx->localRetryInfo_.opInfo.opId));
     447            0 :                 CHK_RET(SetOpExecCmdWithOpId(retryCtx->GetH2dPtr(), KfcCommand::kStopExec, commandinfo.opId));
     448            0 :                 nextState = RETRY_STATE_POLL_STREAM_STOPED;
     449              :             }
     450            0 :             break;
     451            0 :         case RETRY_CMD_CLEAR_STREAM:
     452            0 :             if (curState == RETRY_STATE_WAIT_CMD_CLEAR_STREAM) {
     453            0 :                 CHK_RET(ClearStreamWithOpId(
     454              :                     retryCtx->opStreamPtr_, HcclRtStreamClearStep::HCCL_STREAM_CLEAR, commandinfo.opId,
     455              :                     retryCtx->localRetryInfo_.opInfo.opId));
     456            0 :                 nextState = RETRY_STATE_RESP_STREAM_CLEARED;
     457              :             }
     458            0 :             break;
     459            0 :         case RETRY_CMD_STOP_TRANSPORT:
     460            0 :             if (curState == RETRY_STATE_WAIT_CMD_STOP_TRANSPORT) {
     461            0 :                 CHK_RET(SetTransportStatusForStop(retryCtx));
     462            0 :                 nextState = RETRY_STATE_RESP_STOP_TRANSPORT;
     463              :             }
     464            0 :             break;
     465            0 :         case RETRY_CMD_CHECK_LINK:
     466            0 :             if (curState == RETRY_STATE_WAIT_CMD_CHECK_LINK) {
     467            0 :                 u32& retryCnt = retryCtx->localRetryInfo_.opInfo.execStatus.retryInfo.retryCount;
     468            0 :                 CommConfiger& commConfiger = CommConfiger::GetInstance();
     469            0 :                 u32 waitTime = (retryCnt == 0) ? commConfiger.GetCommConfigRetryHoldTime(retryCtx->group_) :
     470            0 :                                                  commConfiger.GetCommConfigRetryIntervalTime(retryCtx->group_);
     471            0 :                 constexpr u32 TIME_MS_TO_US = 1000;
     472            0 :                 SaluSleep(waitTime * TIME_MS_TO_US);
     473            0 :                 HCCL_RUN_INFO("[OpRetry][Agent]wait for [%u]ms until the link recovers", waitTime);
     474            0 :                 CHK_RET(GetLinkPortStatus(retryCtx, retryCtx->linkPortStatus_));
     475            0 :                 nextState = RETRY_STATE_RESP_LINK_CHECKED;
     476              :             }
     477            0 :             break;
     478            0 :         case RETRY_CMD_RESUME_TRANSPORT:
     479            0 :             if (curState == RETRY_STATE_WAIT_CMD_RESUME_TRANSPORT) {
     480            0 :                 CHK_RET(SetTransportStatusForResume(retryCtx));
     481              :                 // 重新建链后给aicpu下发切换链路命令
     482            0 :                 CHK_RET(SetOpChangeLinkInfo(
     483              :                     retryCtx->GetH2dPtr(), KfcCommand::kChangeLink, retryCtx->localChangeLinkInfo_));
     484            0 :                 nextState = RETRY_STATE_POLL_AICPU_CHANGED;
     485              :             }
     486            0 :             break;
     487            0 :         case RETRY_CMD_RESET_NOTIFY:
     488            0 :             if (curState == RETRY_STATE_WAIT_CMD_RESET_NOTIFY) {
     489            0 :                 CHK_RET(ResetNotify(retryCtx));
     490            0 :                 nextState = RETRY_STATE_RESP_NOTIFY_RESETED;
     491              :             }
     492            0 :             break;
     493            0 :         case RETRY_CMD_CHECK_OPNAME:
     494            0 :             if (curState == RETRY_STATE_WAIT_CMD_CHECK) {
     495            0 :                 CHK_RET(GetRetryInfo(retryCtx, retryCtx->localRetryInfo_));
     496            0 :                 nextState = RETRY_STATE_RESP_CHECK_INFO;
     497              :             }
     498            0 :             break;
     499            0 :         case RETRY_CMD_CAN_RETRY:
     500            0 :             if (curState == RETRY_STATE_WAIT_CMD_CAN_RETRY) {
     501            0 :                 bool isSendRecv = HcclCMDType::HCCL_CMD_SEND == retryCtx->localRetryInfo_.opInfo.opId.opType
     502            0 :                                   || HcclCMDType::HCCL_CMD_RECEIVE == retryCtx->localRetryInfo_.opInfo.opId.opType;
     503            0 :                 u32 dstRank = retryCtx->localRetryInfo_.rankId == retryCtx->localRetryInfo_.opInfo.opId.detRank ?
     504              :                                   retryCtx->localRetryInfo_.opInfo.opId.srcRank :
     505              :                                   retryCtx->localRetryInfo_.opInfo.opId.detRank;
     506            0 :                 if (isSendRecv) {
     507            0 :                     Heartbeat::GetInstance(retryCtx->deviceLogicId_).ClearCqeErr(retryCtx->group_, dstRank);
     508            0 :                 } else if (HcclCMDType::HCCL_CMD_BATCH_SEND_RECV == retryCtx->localRetryInfo_.opInfo.opId.opType) {
     509            0 :                     ResetBatchSendRecvRdmaErr(retryCtx, dstRank);
     510              :                 } else {
     511            0 :                     Heartbeat::GetInstance(retryCtx->deviceLogicId_).ClearAllCqeErr(retryCtx->group_);
     512              :                 }
     513            0 :                 CHK_RET(SetOpExecCmdWithOpId(retryCtx->GetH2dPtr(), KfcCommand::kRetry, commandinfo.opId));
     514            0 :                 nextState = RETRY_STATE_POLL_AICPU_RETRYEND;
     515              :             }
     516            0 :             break;
     517            0 :         case RETRY_CMD_RETRY_CONSTRAINT_FAIL:
     518            0 :             nextState = RETRY_STATE_AGENT_RETRY_FAIL;
     519            0 :             retryCtx->localRetryInfo_.isNeedReportOpRetryErr = true;
     520            0 :             HCCL_RUN_INFO("[OpRetry][Agent]Retry is constraint(OpName is inconsistent or Inplace Error)");
     521            0 :             break;
     522            0 :         case RETRY_CMD_RETRY_FAIL:
     523            0 :             nextState = RETRY_STATE_AGENT_RETRY_FAIL;
     524            0 :             break;
     525            0 :         default: { // 命令非当前状态预期, 不处理
     526            0 :             break;
     527              :         }
     528              :     }
     529            0 :     return HCCL_SUCCESS;
     530              : }
     531              : 
     532            0 : void OpRetryAgentWaitCmd::ResetBatchSendRecvRdmaErr(RetryContext* retryCtx, u32 dstRank)
     533              : {
     534            0 :     bool isBatchSendRecv = (retryCtx->localRetryInfo_.opInfo.opId.opType == HcclCMDType::HCCL_CMD_BATCH_SEND_RECV);
     535            0 :     if (isBatchSendRecv) {
     536            0 :         auto curOpIdTag = std::string(reinterpret_cast<const char*>(retryCtx->localRetryInfo_.opInfo.opId.tag));
     537            0 :         auto curOpIdindex = retryCtx->localRetryInfo_.opInfo.opId.index;
     538            0 :         auto remainSendOpIdTag = std::string(reinterpret_cast<const char*>(retryCtx->RemainSendOpId_.tag));
     539            0 :         auto remainRecvOpIdTag = std::string(reinterpret_cast<const char*>(retryCtx->RemainRecvOpId_.tag));
     540            0 :         if (curOpIdTag == remainSendOpIdTag && curOpIdindex == retryCtx->RemainSendOpId_.index) {
     541            0 :             retryCtx->isBSRRdmaSendError_ = false;
     542            0 :             HCCL_INFO(
     543              :                 "[OpRetry][Agent] bsr send clear cqe err, remoterank[%u], qpn[%u]", dstRank,
     544              :                 retryCtx->RemainSendOpId_.bsrInfo[HCCL_SEND].tpQpn);
     545            0 :             Heartbeat::GetInstance(retryCtx->deviceLogicId_)
     546            0 :                 .ClearCqeErr(retryCtx->group_, dstRank, retryCtx->RemainSendOpId_.bsrInfo[HCCL_SEND].tpQpn);
     547              :         }
     548            0 :         if (curOpIdTag == remainRecvOpIdTag && curOpIdindex == retryCtx->RemainRecvOpId_.index) {
     549            0 :             retryCtx->isBSRRdmaRecvError_ = false;
     550            0 :             HCCL_INFO(
     551              :                 "[OpRetry][Agent] bsr recv clear cqe err, remoterank[%u], qpn[%u]", dstRank,
     552              :                 retryCtx->RemainRecvOpId_.bsrInfo[HCCL_RECV].tpQpn);
     553            0 :             Heartbeat::GetInstance(retryCtx->deviceLogicId_)
     554            0 :                 .ClearCqeErr(retryCtx->group_, dstRank, retryCtx->RemainRecvOpId_.bsrInfo[HCCL_RECV].tpQpn);
     555              :         }
     556            0 :     }
     557            0 :     return;
     558              : }
     559              : 
     560            1 : HcclResult OpRetryAgentPollAicpuStop::ProcessEvent(RetryContext* retryCtx)
     561              : {
     562            1 :     std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
     563            1 :     const std::chrono::seconds timeout = std::chrono::seconds(OP_RETRY_WAIT_AICPU_TIMEOUT);
     564            1 :     RetryState curState = retryCtx->GetRetryState();
     565            1 :     RetryState nextState = RETRY_STATE_RESERVED;
     566              :     while (true) {
     567            1 :         CHK_PRT_RET(
     568              :             retryCtx->isAgentStateWaitResume_,
     569              :             HCCL_RUN_INFO("[OpRetry][Agent]switched state form poll aicpu to wait resume"), HCCL_SUCCESS);
     570              :         // 读取aicpuCtx中的状态
     571            1 :         KfcExecStatus& opInfo = retryCtx->localRetryInfo_.opInfo;
     572            1 :         CHK_RET(GetOpExecInfo(retryCtx->GetD2hPtr(), opInfo));
     573            1 :         const KfcStatus& aicpuState = opInfo.execStatus.kfcStatus;
     574            1 :         const char* tag = reinterpret_cast<const char*>(opInfo.opId.tag);
     575            1 :         u32 index = opInfo.opId.index;
     576            1 :         KfcError errorCode = opInfo.execStatus.kfcError;
     577              : 
     578            2 :         std::string curFaultTag = std::string(reinterpret_cast<const char*>(retryCtx->curFaultOpId.tag));
     579            1 :         std::string curd2hTag = std::string(reinterpret_cast<const char*>(opInfo.opId.tag));
     580            1 :         switch (curState) {
     581            1 :             case RETRY_STATE_POLL_AICPU_STOPED:
     582            1 :                 if (aicpuState == KfcStatus::kStoplaunch || aicpuState == KfcStatus::kStopExec) {
     583            0 :                     if ((retryCtx->curFaultOpId.isSendRecv && curFaultTag == curd2hTag) || !opInfo.opId.isSendRecv) {
     584            0 :                         HCCL_RUN_INFO(
     585              :                             "[OpRetry][Agent]curFaultTag[%s] curd2hTag[%s], isSendRecv[%u]", curFaultTag.c_str(),
     586              :                             curd2hTag.c_str(), retryCtx->curFaultOpId.isSendRecv);
     587            0 :                         nextState = RETRY_STATE_RESP_AICPU_STOPED;
     588              :                     }
     589            1 :                 } else if (aicpuState == KfcStatus::kRetryError && errorCode == KfcError::kExecConstraint) {
     590            1 :                     retryCtx->localRetryInfo_.isNeedReportOpRetryErr = true;
     591            1 :                     HCCL_ERROR("[OpRetry][Agent]can not retry for constraint");
     592            1 :                     nextState = RETRY_STATE_RESP_RUNNING_ERR;
     593            1 :                     break;
     594              :                 }
     595            0 :                 break;
     596            0 :             case RETRY_STATE_POLL_STREAM_STOPED:
     597            0 :                 if (aicpuState == KfcStatus::kStopExec) {
     598            0 :                     nextState = RETRY_STATE_RESP_STREAM_STOPED;
     599            0 :                 } else if (aicpuState == KfcStatus::kRetryError && errorCode == KfcError::kExecConstraint) {
     600            0 :                     retryCtx->localRetryInfo_.isNeedReportOpRetryErr = true;
     601            0 :                     HCCL_ERROR("[OpRetry][Agent]can not retry for constraint");
     602            0 :                     nextState = RETRY_STATE_RESP_RUNNING_ERR;
     603            0 :                     break;
     604              :                 }
     605            0 :                 break;
     606            0 :             case RETRY_STATE_POLL_AICPU_CHANGED:
     607            0 :                 HCCL_RUN_INFO(
     608              :                     "[OpRetry][Agent]OpRetryAgentPollAicpuStop hostState[%s], aicpuState[%d]",
     609              :                     GetReadableState(curState), aicpuState);
     610            0 :                 if (aicpuState == KfcStatus::kChanged) {
     611            0 :                     nextState = RETRY_STATE_RESP_RESUME_TRANSPORT;
     612              :                 }
     613            0 :                 break;
     614            0 :             case RETRY_STATE_POLL_AICPU_RETRYEND:
     615            0 :                 if (aicpuState == KfcStatus::kStoplaunch || aicpuState == KfcStatus::kRuning
     616            0 :                     || aicpuState == KfcStatus::kEnd) {
     617            0 :                     nextState = RETRY_STATE_RESP_AICPU_RETRYEND;
     618              :                 }
     619            0 :                 break;
     620            0 :             default: {
     621            0 :                 HCCL_ERROR(
     622              :                     "[OpRetry][Agent]OpRetryAgentPollAicpuStop state[%s] is invalid", GetReadableState(curState));
     623            0 :                 return HCCL_E_INTERNAL;
     624              :             }
     625              :         }
     626              : 
     627              :         // 执行成功, 跳出循环进入下一个状态
     628            1 :         if (nextState != RETRY_STATE_RESERVED) {
     629            1 :             HCCL_RUN_INFO(
     630              :                 "[OpRetry][Agent]OpRetryAgentPollAicpuStop success, retryState[%s], aicpuState[%d], "
     631              :                 "tag[%s], index[%u]",
     632              :                 GetReadableState(curState), aicpuState, tag, index);
     633            1 :             HCCL_RUN_INFO(
     634              :                 "[OpRetry][agent pollaicpu OpId]tag[%s], index[%u], srcRank[%u], detRank[%u], isSendRecv[%d],"
     635              :                 "streamid[%u], retryCnt[%u]",
     636              :                 opInfo.opId.tag, opInfo.opId.index, opInfo.opId.srcRank, opInfo.opId.detRank, opInfo.opId.isSendRecv,
     637              :                 opInfo.opId.streamId, opInfo.execStatus.retryInfo.retryCount);
     638            1 :             break;
     639              :         }
     640              : 
     641              :         // 超时机制
     642            0 :         std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
     643            0 :         const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime);
     644            0 :         CHK_PRT_BREAK(
     645              :             elapsed >= timeout,
     646              :             HCCL_ERROR(
     647              :                 "[OpRetry][Agent]OpRetryAgentPollAicpuStop timeout, retryState[%s], aicpuState[%d], "
     648              :                 "tag[%s], index[%u]",
     649              :                 GetReadableState(curState), aicpuState, tag, index),
     650              :             nextState = RETRY_STATE_RESP_RUNNING_ERR);
     651              : 
     652              :         // 轮询间隔
     653            0 :         SaluSleep(OP_RETRY_POLL_AICPU_STATE_INTERVAL);
     654            2 :     }
     655              : 
     656            1 :     CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
     657            1 :     return HCCL_SUCCESS;
     658              : }
     659              : 
     660              : // 向server状态机发送主备链路信息
     661            0 : HcclResult OpRetryAgentResponseLinkInfo::ProcessEvent(RetryContext* retryCtx)
     662              : {
     663            0 :     HCCL_INFO("[OpRetry][Agent]OpRetryAgentResponseLinkInfo begin");
     664              :     // 获取预期的下一个状态
     665            0 :     RetryState nextState = RETRY_STATE_WAIT_CHANGE_LINK_INFO;
     666              : 
     667              :     // 发送数据
     668            0 :     HcclResult ret = IssueLinkPortCheckResult(retryCtx->agentSocket_, retryCtx->linkPortStatus_);
     669            0 :     CHK_PRT_RET(
     670              :         ret != HCCL_SUCCESS, HCCL_ERROR("[OpRetry][Agent]OpRetryAgentResponseLinkInfo IssueResponse fail"), ret);
     671            0 :     CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
     672            0 :     HCCL_INFO("[OpRetry][Agent]OpRetryAgentResponseLinkInfo success");
     673            0 :     return HCCL_SUCCESS;
     674              : }
     675              : 
     676            0 : void OpRetryAgentWaitChangeLinkInfo::UpdateChangeLinkInfo(
     677              :     ChangeLinkInfo& localChangeLinkInfo, ChangeLinkInfo& recvChangeLinkInfo)
     678              : {
     679              :     // 记录localChangeLinkInfo_中已有的数据
     680            0 :     std::unordered_map<u32, u32> remoteRankPosition; // {remoteRank: position}
     681            0 :     for (u32 i = 0; i < localChangeLinkInfo.remoteRankNum; i++) {
     682            0 :         remoteRankPosition.insert({localChangeLinkInfo.remoteRankList[i], i});
     683              :     }
     684              :     // 将接收到的recvChangeLinkInfo更新到localChangeLinkInfo_中
     685            0 :     for (u32 i = 0; i < recvChangeLinkInfo.remoteRankNum; i++) {
     686            0 :         u32 remoteRank = recvChangeLinkInfo.remoteRankList[i];
     687            0 :         bool isUseDefaultPort = recvChangeLinkInfo.isUseDefaultPort[i];
     688            0 :         if (remoteRankPosition.find(remoteRank) != remoteRankPosition.end()) {
     689              :             // 若remoteRank在localChangeLinkInfo_中,更新其端口使用情况
     690            0 :             localChangeLinkInfo.isUseDefaultPort[remoteRankPosition[remoteRank]] = isUseDefaultPort;
     691            0 :             HCCL_RUN_INFO(
     692              :                 "[OpRetry][Agent]update remoteRank[%u] to isUseDefaultPort[%d]", remoteRank, isUseDefaultPort);
     693              :         } else {
     694              :             // 若remoteRank不在localChangeLinkInfo_中,则添加到localChangeLinkInfo_中
     695            0 :             u32 position = localChangeLinkInfo.remoteRankNum;
     696            0 :             localChangeLinkInfo.remoteRankList[position] = remoteRank;
     697            0 :             localChangeLinkInfo.isUseDefaultPort[position] = isUseDefaultPort;
     698            0 :             localChangeLinkInfo.remoteRankNum += 1;
     699            0 :             HCCL_RUN_INFO(
     700              :                 "[OpRetry][Agent]insert remoteRank[%u] to isUseDefaultPort[%d]", remoteRank, isUseDefaultPort);
     701              :         }
     702              :     }
     703            0 :     return;
     704            0 : }
     705              : 
     706              : // 从server状态机接收主备借轨命令
     707            0 : HcclResult OpRetryAgentWaitChangeLinkInfo::ProcessEvent(RetryContext* retryCtx)
     708              : {
     709            0 :     HCCL_INFO("[OpRetry][Agent]OpRetryAgentWaitChangeLinkInfo begin");
     710            0 :     RetryState nextState = RETRY_STATE_RESERVED;
     711              : 
     712            0 :     std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
     713            0 :     const u32 timeoutValue = std::max(static_cast<u32>(GetExternalInputHcclLinkTimeOut()), OP_RETRY_SEND_RECV_TIMEOUT)
     714            0 :                              + OP_RETRY_WAIT_AICPU_TIMEOUT;
     715            0 :     const std::chrono::seconds timeout = std::chrono::seconds(timeoutValue);
     716            0 :     ChangeLinkInfo tmpRecvChangeLinkInfo;
     717              :     // 接收到命令和当前状态不匹配时, 不做处理, 等待下一个命令, 直到命令正确或者超时
     718              :     while (true) {
     719            0 :         std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
     720            0 :         const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime);
     721            0 :         CHK_PRT_RET(elapsed > timeout, HCCL_ERROR("[OpRetry]WaitChangeLink timeout"), HCCL_E_TIMEOUT);
     722            0 :         CHK_PRT_RET(
     723              :             retryCtx->isAgentStateWaitResume_,
     724              :             HCCL_RUN_INFO("[OpRetry][Agent]switched state form wait change link to wait resume"), HCCL_SUCCESS);
     725              : 
     726            0 :         HcclResult ret = WaitChangeLink(retryCtx->agentSocket_, tmpRecvChangeLinkInfo);
     727            0 :         if (ret == HCCL_SUCCESS) {
     728            0 :             HCCL_INFO("[OpRetry][Agent]WaitChangeLink success");
     729              :             // 将接收到的ChangeLinkInfo更新到已有的changeLinkInfo中
     730            0 :             UpdateChangeLinkInfo(retryCtx->localChangeLinkInfo_, tmpRecvChangeLinkInfo);
     731              :             // agent接收的changeLinkInfo信息
     732            0 :             std::string changeLinkInfoStr = "agent:";
     733            0 :             for (u32 i = 0; i < retryCtx->localChangeLinkInfo_.remoteRankNum; i++) {
     734              :                 changeLinkInfoStr
     735            0 :                     += (std::to_string(retryCtx->localChangeLinkInfo_.remoteRankList[i]) + ":"
     736            0 :                         + std::to_string(retryCtx->localChangeLinkInfo_.isUseDefaultPort[i]) + "; ");
     737              :             }
     738            0 :             HCCL_RUN_INFO("[OpRetry][Agnet]changeLinkInfoStr:%s", changeLinkInfoStr.c_str());
     739              : 
     740              :             // 收到changelinkinfo后切换到RETRY_STATE_WAIT_CMD_RESUME_TRANSPORT状态等待接收resume transport命令
     741            0 :             nextState = RETRY_STATE_WAIT_CMD_RESUME_TRANSPORT;
     742            0 :             break;
     743            0 :         }
     744            0 :     }
     745            0 :     CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
     746            0 :     HCCL_INFO("[OpRetry][Agent]OpRetryAgentWaitChangeLinkInfo success");
     747            0 :     return HCCL_SUCCESS;
     748              : }
     749              : 
     750              : // RETRY_STATE_AGENT_RETRY_FAIL
     751            0 : HcclResult OpRetryAgentRetryFail::ProcessEvent(RetryContext* retryCtx)
     752              : {
     753            0 :     HCCL_INFO("[OpRetry][Agent]OpRetryAgentRetryFail, set state to running");
     754            0 :     if (retryCtx->localRetryInfo_.isNeedReportOpRetryErr) {
     755            0 :         CHK_RET(SetOpExecCmd(retryCtx->GetH2dPtr(), KfcCommand::kReportRetryErr));
     756            0 :         HCCL_RUN_INFO(
     757              :             "[OpRetry][Agent]OpRetryAgentRetryFail, isNeeReportOpRetryErr[%d]",
     758              :             retryCtx->localRetryInfo_.isNeedReportOpRetryErr);
     759              :     } else {
     760            0 :         CHK_RET(SetOpExecCmd(retryCtx->GetH2dPtr(), KfcCommand::kExit));
     761              :     }
     762            0 :     CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_AGENT_RUNNING, retryCtx));
     763            0 :     Heartbeat::GetInstance(retryCtx->deviceLogicId_).BroadcastCqeErr(retryCtx->group_);
     764            0 :     return HCCL_SUCCESS;
     765              : }
     766              : 
     767            0 : HcclResult OpRetryAgentWaitResume::ProcessEvent(RetryContext* retryCtx)
     768              : {
     769            0 :     if (!retryCtx->isAgentStateWaitResume_ && !retryCtx->haveCommEnableBackupLink_) {
     770            0 :         CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_AGENT_RUNNING, retryCtx));
     771            0 :         HCCL_RUN_INFO(
     772              :             "[OpRetry][Agent]OpRetryAgentWaitResume, group[%s], no comm enable backup link, set state to running",
     773              :             retryCtx->group_.c_str());
     774            0 :         return HCCL_SUCCESS;
     775              :     }
     776            0 :     RetryCommandInfo commandInfo;
     777            0 :     HcclResult ret = WaitCommandWithOpId(retryCtx->agentSocket_, commandInfo);
     778            0 :     if (ret == HCCL_SUCCESS) {
     779            0 :         HCCL_INFO(
     780              :             "[OpRetry][Agent]OpRetryAgentWaitResume, rankId[%u], command[%s], group[%s], isAgentStateWaitResume_[%d]",
     781              :             retryCtx->localRetryInfo_.rankId, GetReadableCmd(commandInfo.command), retryCtx->group_.c_str(),
     782              :             retryCtx->isAgentStateWaitResume_);
     783              :     }
     784            0 :     if (commandInfo.command == RESUME_CMD_RUNNING) {
     785            0 :         retryCtx->isRecivedCmdToRunning = true;
     786            0 :     } else if (commandInfo.command == RESUME_CMD_CHECK_LINK) {
     787            0 :         retryCtx->isRecivedCmdToCheckLink = true;
     788              :     }
     789            0 :     if (!retryCtx->isAgentStateWaitResume_ && retryCtx->isRecivedCmdToRunning) {
     790            0 :         CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_AGENT_RUNNING, retryCtx));
     791            0 :         retryCtx->isRecivedCmdToRunning = false;
     792            0 :         HCCL_RUN_INFO("[OpRetry][Agent]OpRetryAgentWaitResume, set state to running");
     793            0 :     } else if (!retryCtx->isAgentStateWaitResume_ && retryCtx->isRecivedCmdToCheckLink) {
     794            0 :         CHK_RET(CreateOpRetryAgentByState(RETRY_RESUME_STATE_AGENT_CHECK_LINK, retryCtx));
     795            0 :         HCCL_RUN_INFO("[OpRetry][Agent]OpRetryAgentWaitResume, set state to check link");
     796              :     }
     797            0 :     return HCCL_SUCCESS;
     798              : }
     799              : 
     800              : // RETRY_STATE_WAIT_CMD_SEND_AICPU
     801            2 : HcclResult SwitchNicAgentWaitCmd::ParseCommand(RetryContext* retryCtx, RetryCommand& command, RetryState& nextState)
     802              : {
     803            2 :     switch (command) {
     804            2 :         case RETRY_CMD_NOTIFY_SWITCH_SUC:
     805            2 :             HCCL_INFO("[SwitchNic][Agent][WaitCmd] switch nic success, rank[%u]", retryCtx->rankId_);
     806              :             // OpRetryAgent接收到全局通信域的成功/错误信息后,刷新lastLinkPortStatus_信息
     807            4 :             for (u32 i = 0; i < retryCtx->switchInfo_.switchRankNum; i++) {
     808            2 :                 if (retryCtx->switchInfo_.switchRankList[i] == retryCtx->rankId_) {
     809            2 :                     retryCtx->isUseDefaultPort_ = !retryCtx->switchInfo_.switchUseBackup[i];
     810              :                 }
     811              :             }
     812            6 :             for (u32 i = 0; i < retryCtx->switchInfo_.remoteRankNum; i++) {
     813            4 :                 if (retryCtx->switchInfo_.remoteRankNicStatus[i] == CONNECT_REMOTE_DEFAULT) {
     814            2 :                     retryCtx->lastLinkPortStatus_[i] = true;
     815              :                 }
     816            4 :                 if (retryCtx->switchInfo_.remoteRankNicStatus[i] == CONNECT_REMOTE_BACKUP) {
     817            2 :                     retryCtx->lastLinkPortStatus_[i] = false;
     818              :                 }
     819              :             }
     820            2 :             CHK_RET(SetOpExecCmd(retryCtx->GetH2dPtr(), KfcCommand::kAllSwitched));
     821            2 :             nextState = RETRY_STATE_AGENT_RUNNING;
     822            2 :             break;
     823            0 :         case RETRY_CMD_NOTIFY_SWITCH_FAIL:
     824            0 :             HCCL_ERROR("[SwitchNic][Agent][WaitCmd] switch nic failed, rank[%u]", retryCtx->rankId_);
     825            0 :             CHK_RET(SetOpExecCmd(retryCtx->GetH2dPtr(), KfcCommand::kSwitchFail));
     826            0 :             nextState = RETRY_STATE_AGENT_RUNNING;
     827            0 :             break;
     828            0 :         case RETRY_CMD_RUNNING:
     829            0 :             HCCL_DEBUG(
     830              :                 "[SwitchNic][Agent][WaitCmd] rank[%u] recv running command from server, ignored", retryCtx->rankId_);
     831            0 :             break;
     832            0 :         default: { // 命令非当前状态预期
     833            0 :             HCCL_ERROR(
     834              :                 "[SwitchNic][Agent][WaitCmd] rank[%u], recv unexpected parse command[%s:%u].", retryCtx->rankId_,
     835              :                 GetReadableCmd(command), command);
     836            0 :             return HCCL_E_INTERNAL;
     837              :         }
     838              :     }
     839            2 :     return HCCL_SUCCESS;
     840              : }
     841              : 
     842            2 : HcclResult SwitchNicAgentWaitCmd::ProcessEvent(RetryContext* retryCtx)
     843              : {
     844            2 :     HCCL_RUN_INFO("[SwitchNic][Agent] rank[%u] begin to wait server cmd, set state to wait", retryCtx->rankId_);
     845            2 :     RetryState curState = retryCtx->localRetryInfo_.retryState;
     846            2 :     RetryState nextState = RETRY_STATE_RESERVED;
     847              :     RetryCommand command;
     848            2 :     std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
     849            2 :     const auto timeout = std::chrono::seconds(GetExternalInputHcclLinkTimeOut() * ACTIVE_SWITCH_TIMES);
     850              : 
     851              :     // 接收到命令和当前状态不匹配时, 不做处理, 等待下一个命令, 直到命令正确或者超时
     852              :     while (true) {
     853            2 :         CHK_PRT_RET(
     854              :             retryCtx->isAgentStateWaitResume_,
     855              :             HCCL_RUN_INFO("[OpRetry][Agent]switched state form switch nic to wait resume"), HCCL_SUCCESS);
     856            2 :         std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
     857            2 :         const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime);
     858            2 :         CHK_PRT_RET(
     859              :             elapsed > timeout,
     860              :             HCCL_ERROR("[SwitchNic][Agent] timeout in getting cmd from server, waitime[%u s>%u s]", elapsed, timeout),
     861              :             HCCL_E_TIMEOUT);
     862              : 
     863            2 :         HcclResult ret = WaitCommand(retryCtx->agentSocket_, command);
     864            2 :         if (ret == HCCL_SUCCESS) {
     865            2 :             HCCL_DEBUG(
     866              :                 "[SwitchNic][Agent]SwitchNicAgentWaitCmd state[%s] command[%s:%u]", GetReadableState(curState),
     867              :                 GetReadableCmd(command), command);
     868            2 :             CHK_PRT(ParseCommand(retryCtx, command, nextState));
     869            2 :             if (nextState != RETRY_STATE_RESERVED) { // 接收到的命令有效
     870            2 :                 break;
     871              :             }
     872              :         }
     873            0 :     }
     874            2 :     CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
     875            2 :     return HCCL_SUCCESS;
     876              : }
     877              : 
     878            1 : HcclResult SwitchNicAgentSendSwitchInfo::ChangeAicpuStatus(RetryContext* retryCtx)
     879              : {
     880            1 :     HcclResult ret = SetOpExecCmd(retryCtx->GetH2dPtr(), KfcCommand::kWaitSwitchNic);
     881            1 :     if (ret != HCCL_SUCCESS) {
     882            0 :         HCCL_ERROR(
     883              :             "[SwitchNic][Agent] rank[%u], ChangeAicpuStatus, SetOpExecCmd to waitSwitchNic fail, ", retryCtx->rankId_);
     884              :     }
     885            1 :     std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
     886            1 :     const std::chrono::seconds timeout = std::chrono::seconds(OP_RETRY_WAIT_AICPU_TIMEOUT);
     887              :     while (true) {
     888      2460104 :         CHK_PRT_RET(
     889              :             retryCtx->isAgentStateWaitResume_,
     890              :             HCCL_RUN_INFO("[OpRetry][Agent]switched state form send swhitch Nic info to wait resume"), HCCL_SUCCESS);
     891      2460103 :         KfcExecStatus& opInfo = retryCtx->localRetryInfo_.opInfo;
     892      2460103 :         CHK_RET(GetOpExecInfo(retryCtx->GetD2hPtr(), opInfo));
     893      2460103 :         const KfcStatus& aicpuState = opInfo.execStatus.kfcStatus;
     894      2460103 :         if (aicpuState == KfcStatus::kWaitSwitchRes) {
     895            0 :             break;
     896              :         }
     897              : 
     898      2460103 :         std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
     899      2460103 :         const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime);
     900      2460103 :         CHK_PRT_RET(
     901              :             elapsed >= timeout,
     902              :             HCCL_ERROR(
     903              :                 "[SwitchNic][Agent]SwitchNicAgentSendSwitchInfo, WaitAicpuResponse timeout, "
     904              :                 "rank[%u], aicpuState[%d]",
     905              :                 retryCtx->rankId_, aicpuState),
     906              :             HCCL_E_TIMEOUT);
     907      2460102 :     }
     908            0 :     return HCCL_SUCCESS;
     909              : }
     910              : 
     911            1 : HcclResult SwitchNicAgentSendSwitchInfo::CheckLocalPortStatus(RetryContext* retryCtx)
     912              : {
     913            1 :     HcclResult ret = HcclNetDevGetPortStatus(retryCtx->netDevCtx_, retryCtx->linkPortStatus_.defaultPort);
     914            1 :     CHK_PRT_RET(
     915              :         ret != HCCL_SUCCESS,
     916              :         HCCL_ERROR("[SwitchNic][Agent] rank[%u], get default port status fail.", retryCtx->rankId_), HCCL_E_INTERNAL);
     917            1 :     ret = HcclNetDevGetPortStatus(retryCtx->backUpNetDevCtx_, retryCtx->linkPortStatus_.backupPort);
     918            1 :     CHK_PRT_RET(
     919              :         ret != HCCL_SUCCESS, HCCL_ERROR("[SwitchNic][Agent] rank[%u], get backup port status fail.", retryCtx->rankId_),
     920              :         HCCL_E_INTERNAL);
     921            1 :     return HCCL_SUCCESS;
     922              : }
     923              : 
     924              : // RETRY_STATE_SEND_SWITCH_INFO
     925            1 : HcclResult SwitchNicAgentSendSwitchInfo::ProcessEvent(RetryContext* retryCtx)
     926              : {
     927            1 :     HCCL_RUN_INFO("[SwitchNic][Agent] rank[%u] begin to send switch info, set state to switch", retryCtx->rankId_);
     928              : 
     929            1 :     ActiveSwitchInfo& switchInfo = retryCtx->switchInfo_;
     930            1 :     const KfcStatus transportStatus = retryCtx->localRetryInfo_.opInfo.execStatus.kfcStatus;
     931            1 :     switchInfo.refreshTransportFin = (transportStatus == KfcStatus::kPlanSwitch) ? true : false;
     932            1 :     if (!switchInfo.refreshTransportFin) {
     933            0 :         HCCL_ERROR(
     934              :             "[SwitchNic][Agent] rank[%u], recv refresh transport kfcStatus[%u], "
     935              :             "refreshTransportFin is set to false, ",
     936              :             retryCtx->rankId_, transportStatus);
     937              :     }
     938              : 
     939            1 :     HcclResult ret = ChangeAicpuStatus(retryCtx);
     940            1 :     if (ret != HCCL_SUCCESS) {
     941            1 :         switchInfo.refreshTransportFin = false;
     942            1 :         HCCL_ERROR(
     943              :             "[SwitchNic][Agent] rank[%u], ChangeAicpuStatus fail, refreshTransportFin is set to false.",
     944              :             retryCtx->rankId_);
     945              :     }
     946              : 
     947              :     // 校验本端准备使用的主/备网卡状态
     948            1 :     ret = CheckLocalPortStatus(retryCtx);
     949            1 :     if (ret != HCCL_SUCCESS) {
     950            0 :         switchInfo.localPortsCheckRet = false;
     951            0 :         HCCL_ERROR(
     952              :             "[SwitchNic][Agent] rank[%u], get local port status fail, "
     953              :             "localPortsCheckRet is set to false.",
     954              :             retryCtx->rankId_);
     955              :     }
     956              : 
     957              :     // 并将本端完成借轨的flag, 以及之前登记的switchRanks信息发送给OpRetryServer
     958            1 :     bool needCheckDefaultNic = false;
     959            1 :     bool needCheckBackupNic = false;
     960            1 :     ret = GetSwitchRanks(retryCtx, needCheckDefaultNic, needCheckBackupNic);
     961            1 :     if (ret != HCCL_SUCCESS) {
     962            0 :         switchInfo.refreshTransportFin = false;
     963            0 :         HCCL_ERROR(
     964              :             "[SwitchNic][Agent] rank[%u], get switch rank info fail, "
     965              :             "refreshTransportFin is set to false.",
     966              :             retryCtx->rankId_);
     967              :     }
     968              : 
     969            1 :     switchInfo.defaultPortStatus = retryCtx->linkPortStatus_.defaultPort;
     970            1 :     switchInfo.backupPortStatus = retryCtx->linkPortStatus_.backupPort;
     971            1 :     if ((needCheckDefaultNic && !switchInfo.defaultPortStatus)
     972            0 :         || (needCheckBackupNic && !switchInfo.backupPortStatus)) {
     973            1 :         switchInfo.localPortsCheckRet = false;
     974            1 :         HCCL_ERROR(
     975              :             "[SwitchNic][Agent] localPortsCheckRet is false, needCheckDefaultNic[%u], needCheckBackupNic[%u],"
     976              :             "localPortsCheckRet[%u], defaultPortStatus[%u], backupPortStatus[%u], rank[%u]",
     977              :             needCheckDefaultNic, needCheckBackupNic, switchInfo.localPortsCheckRet, switchInfo.defaultPortStatus,
     978              :             switchInfo.backupPortStatus, retryCtx->rankId_);
     979              :     } else {
     980            0 :         switchInfo.localPortsCheckRet = true;
     981              :     }
     982            1 :     HCCL_RUN_INFO(
     983              :         "[SwitchNic][Agent] switch info, refresh transport kfcStatus[%u], needCheckDefaultNic[%u], "
     984              :         "needCheckBackupNic[%u], localPortsCheckRet[%u], defaultPortStatus[%u], backupPortStatus[%u], "
     985              :         "refreshTransportFin[%u], switchRankNum[%u], remoteRankNum[%u], rank[%u]",
     986              :         transportStatus, needCheckDefaultNic, needCheckBackupNic, switchInfo.localPortsCheckRet,
     987              :         switchInfo.defaultPortStatus, switchInfo.backupPortStatus, switchInfo.refreshTransportFin,
     988              :         switchInfo.switchRankNum, switchInfo.remoteRankNum, retryCtx->rankId_);
     989              :     //  第一次发送retryInfo,目的是为了server确认为主动接轨场景再接收switchInfo
     990            2 :     RetryInfo retryInfo = {};
     991            1 :     retryInfo.retryState = RETRY_STATE_SEND_SWITCH_INFO;
     992            1 :     retryInfo.rankId = retryCtx->rankId_;
     993            1 :     ret = IssueResponse(retryCtx->agentSocket_, retryInfo);
     994            1 :     if (ret == HCCL_SUCCESS) {
     995            1 :         ret = IssueActiveSwitchInfo(retryCtx->agentSocket_, switchInfo);
     996              :     } else {
     997            0 :         HCCL_ERROR("[SwitchNic][Agent] rank[%u], issue response to server fail.", retryCtx->rankId_);
     998              :     }
     999            1 :     if (ret != HCCL_SUCCESS) {
    1000            0 :         HCCL_ERROR(
    1001              :             "[SwitchNic][Agent] rank[%u], issue response or active switch info to server fail, "
    1002              :             "send result to aicpu.",
    1003              :             retryCtx->rankId_);
    1004            0 :         CHK_RET(SetOpExecCmd(retryCtx->GetH2dPtr(), KfcCommand::kSwitchFail));
    1005            0 :         CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_AGENT_RUNNING, retryCtx));
    1006              :     } else {
    1007            1 :         CHK_RET(CreateOpRetryAgentByState(RETRY_STATE_WAIT_CMD_SEND_AICPU, retryCtx));
    1008              :     }
    1009            1 :     return HCCL_SUCCESS;
    1010              : }
    1011              : 
    1012            0 : HcclResult ResumeAgentCheckLink::ProcessEvent(RetryContext* retryCtx)
    1013              : {
    1014              :     // 快恢阶段需要获取通信域内所有使用RDMA链路的rank列表, isGetGroupAllRemoteRank为true
    1015            0 :     if (!retryCtx->isChangeLinkInfoInit_) {
    1016            0 :         CHK_RET(InitChangeLinkInfo(retryCtx, false, true));
    1017            0 :         retryCtx->isChangeLinkInfoInit_ = true;
    1018              :     } else {
    1019              :         // BatchSendRecv算子增量建链场景
    1020            0 :         CHK_RET(InitChangeLinkInfo(retryCtx, true, true));
    1021              :     }
    1022              : 
    1023            0 :     CHK_RET(SetTransportStatusForStop(retryCtx));
    1024            0 :     RetryState nextState = RETRY_RESUME_STATE_AGENT_CHANGE_LINK;
    1025            0 :     HCCL_RUN_INFO("[OpRetry][Agent]OpRetryAgentWaitResume, start to check link");
    1026              :     // 获取当前主备网口状态,并且回复Server
    1027            0 :     CHK_RET(GetLinkPortStatus(retryCtx, retryCtx->linkPortStatus_, true));
    1028            0 :     HcclResult ret = IssueLinkPortCheckResult(retryCtx->agentSocket_, retryCtx->linkPortStatus_);
    1029            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[OpRetry][Agent]ResumeAgentCheckLink IssueResponse fail"), ret);
    1030            0 :     CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
    1031            0 :     return HCCL_SUCCESS;
    1032              : }
    1033              : 
    1034            0 : HcclResult ResumeAgentChangeLink::ProcessEvent(RetryContext* retryCtx)
    1035              : {
    1036            0 :     HCCL_RUN_INFO(
    1037              :         "[OpRetry][Agent][Resume]ResumeAgentChangeLink group[%s] rank[%d] start", retryCtx->group_.c_str(),
    1038              :         retryCtx->rankId_);
    1039            0 :     RetryState nextState = RETRY_STATE_RESERVED;
    1040              :     // 接收到Server下发的切换链路信息和重建transport命令
    1041            0 :     CHK_RET(WaitResumeCmdResumeTransport(retryCtx));
    1042              :     // 重建当前选择的链路并拷贝到device侧,给aicpu下发切换链路命令
    1043            0 :     CHK_RET(SetTransportStatusForResume(retryCtx));
    1044            0 :     HCCL_INFO(
    1045              :         "[OpRetry][Agent][Resume]ResumeAgentChangeLink group[%s] rank[%d] SetTransportStatusForResume finish",
    1046              :         retryCtx->group_.c_str(), retryCtx->rankId_);
    1047              :     // 等待aicpu切换链路完成
    1048            0 :     CHK_RET(SetOpChangeLinkInfo(retryCtx->GetH2dPtr(), KfcCommand::NsChangeLink, retryCtx->localChangeLinkInfo_));
    1049            0 :     HCCL_INFO(
    1050              :         "[OpRetry][Agent][Resume]ResumeAgentChangeLink group[%s] rank[%d] SetOpChangeLinkInfo finish",
    1051              :         retryCtx->group_.c_str(), retryCtx->rankId_);
    1052            0 :     CHK_RET(WaitAndRespLinkChanged(retryCtx, nextState));
    1053            0 :     if (nextState != RETRY_STATE_AGENT_RUNNING) {
    1054            0 :         HCCL_ERROR("[OpRetry][Agent]ResumeAgentChangeLink WaitAndRespLinkChanged fail, nextState[%s]", nextState);
    1055              :     }
    1056            0 :     CHK_RET(CreateOpRetryAgentByState(nextState, retryCtx));
    1057            0 :     return HCCL_SUCCESS;
    1058              : }
    1059              : 
    1060            0 : HcclResult ResumeAgentChangeLink::WaitResumeCmdResumeTransport(RetryContext* retryCtx)
    1061              : {
    1062            0 :     ChangeLinkInfo tmpRecvChangeLinkInfo;
    1063            0 :     std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
    1064            0 :     const u32 timeoutValue = std::max(static_cast<u32>(GetExternalInputHcclLinkTimeOut()), OP_RETRY_SEND_RECV_TIMEOUT)
    1065            0 :                              + OP_RETRY_WAIT_AICPU_TIMEOUT;
    1066            0 :     const std::chrono::seconds timeout = std::chrono::seconds(timeoutValue);
    1067              :     // 接收到命令和当前状态不匹配时, 不做处理, 等待下一个命令, 直到命令正确或者超时
    1068              :     while (true) {
    1069            0 :         std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
    1070            0 :         const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime);
    1071            0 :         CHK_PRT_RET(elapsed > timeout, HCCL_ERROR("[OpRetry][Agent]ResumeAgentChangeLink timeout"), HCCL_E_TIMEOUT);
    1072              : 
    1073            0 :         HcclResult ret = WaitChangeLink(retryCtx->agentSocket_, tmpRecvChangeLinkInfo);
    1074            0 :         if (ret == HCCL_SUCCESS) {
    1075            0 :             HCCL_INFO(
    1076              :                 "[OpRetry][Agent][Resume]WaitResumeCmdResumeTransport receive changelinkinfo success, rank[%d], "
    1077              :                 "group[%s]",
    1078              :                 retryCtx->rankId_, retryCtx->group_.c_str());
    1079            0 :             UpdateChangeLinkInfo(retryCtx->localChangeLinkInfo_, tmpRecvChangeLinkInfo);
    1080              :             // agent接收到的changeLinkInfo信息
    1081            0 :             std::string changeLinkInfoStr = "agent:";
    1082            0 :             for (u32 i = 0; i < retryCtx->localChangeLinkInfo_.remoteRankNum; i++) {
    1083              :                 changeLinkInfoStr
    1084            0 :                     += (std::to_string(retryCtx->localChangeLinkInfo_.remoteRankList[i]) + ":"
    1085            0 :                         + std::to_string(retryCtx->localChangeLinkInfo_.isUseDefaultPort[i]) + "; ");
    1086              :             }
    1087            0 :             HCCL_RUN_INFO("[OpRetry][Agent][Resume]changeLinkInfoStr:%s", changeLinkInfoStr.c_str());
    1088            0 :             break;
    1089            0 :         }
    1090            0 :     }
    1091            0 :     HCCL_INFO(
    1092              :         "[OpRetry][Agent][Resume]WaitResumeCmdResumeTransport begin to wait command to changelink, rank[%d], group[%s]",
    1093              :         retryCtx->rankId_, retryCtx->group_.c_str());
    1094              :     // 轮询等待接收借轨命令
    1095              :     while (true) {
    1096            0 :         std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
    1097            0 :         const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime);
    1098            0 :         CHK_PRT_RET(elapsed > timeout, HCCL_ERROR("[OpRetry]WaitResumeCmdChangeLink timeout"), HCCL_E_TIMEOUT);
    1099            0 :         RetryCommandInfo commandInfo;
    1100            0 :         HcclResult ret = WaitCommandWithOpId(retryCtx->agentSocket_, commandInfo);
    1101            0 :         if (ret == HCCL_SUCCESS) {
    1102            0 :             if (commandInfo.command == RETRY_CMD_RESUME_TRANSPORT) {
    1103            0 :                 HCCL_RUN_INFO(
    1104              :                     "[OpRetry][Agent][Resume]WaitResumeCmdChangeLink, recv command[%s], group[%s], rankId[%u]",
    1105              :                     GetReadableCmd(commandInfo.command), retryCtx->group_.c_str(), retryCtx->rankId_);
    1106            0 :                 break;
    1107              :             }
    1108              :         }
    1109            0 :     }
    1110            0 :     return HCCL_SUCCESS;
    1111              : }
    1112              : 
    1113            0 : HcclResult ResumeAgentChangeLink::WaitAndRespLinkChanged(RetryContext* retryCtx, RetryState& nextState)
    1114              : {
    1115            0 :     std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
    1116            0 :     const std::chrono::seconds timeout = std::chrono::seconds(OP_RETRY_WAIT_AICPU_TIMEOUT);
    1117            0 :     HCCL_INFO(
    1118              :         "[OpRetry][Agent][Resume]WaitAndRespLinkChanged start, rank[%d], group[%s]", retryCtx->rankId_,
    1119              :         retryCtx->group_.c_str());
    1120              :     while (true) {
    1121            0 :         KfcExecStatus& opInfo = retryCtx->localRetryInfo_.opInfo;
    1122            0 :         CHK_RET(GetOpExecInfo(retryCtx->GetD2hPtr(), opInfo));
    1123            0 :         const KfcStatus& aicpuState = opInfo.execStatus.kfcStatus;
    1124            0 :         if (aicpuState == KfcStatus::kResumeChanged) {
    1125            0 :             nextState = RETRY_STATE_AGENT_RUNNING;
    1126            0 :             CHK_RET(SetOpExecCmd(retryCtx->GetH2dPtr(), KfcCommand::kNone));
    1127            0 :             HCCL_INFO(
    1128              :                 "[OpRetry][Agent][Resume]WaitAndRespLinkChanged, aicpuState[%d], rank[%d], group[%s]", aicpuState,
    1129              :                 retryCtx->rankId_, retryCtx->group_.c_str());
    1130            0 :             break;
    1131              :         }
    1132              :         // 超时机制
    1133            0 :         std::chrono::steady_clock::time_point curTime = std::chrono::steady_clock::now();
    1134            0 :         const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime);
    1135            0 :         CHK_PRT_BREAK(
    1136              :             elapsed >= timeout,
    1137              :             HCCL_ERROR("[OpRetry][Agent][Resume]WaitAndRespLinkChanged timeout, aicpuState[%d]", aicpuState),
    1138              :             nextState = RETRY_STATE_RESP_RUNNING_ERR);
    1139              :         // 轮询间隔
    1140            0 :         SaluSleep(OP_RETRY_POLL_AICPU_STATE_INTERVAL);
    1141            0 :     }
    1142            0 :     if (nextState == RETRY_STATE_AGENT_RUNNING) {
    1143              :         // 回复成功
    1144            0 :         retryCtx->localRetryInfo_.retryState = RETRY_STATE_AGENT_RUNNING;
    1145            0 :         HCCL_INFO(
    1146              :             "[OpRetry][Agent][Resume]WaitAndRespLinkChanged success, rank[%d], group[%s]", retryCtx->rankId_,
    1147              :             retryCtx->group_.c_str());
    1148            0 :         retryCtx->localRetryInfo_.opInfo.execStatus.kfcStatus = KfcStatus::kResumeChanged;
    1149            0 :         HcclResult ret = IssueResponse(retryCtx->agentSocket_, retryCtx->localRetryInfo_);
    1150            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[OpRetry][Agent]ResumeAgentChangeLink IssueResponse fail"), ret);
    1151              :     }
    1152            0 :     return HCCL_SUCCESS;
    1153              : }
    1154              : } // namespace hccl
        

Generated by: LCOV version 2.0-1