LCOV - code coverage report
Current view: top level - legacy/ascend910/platform/resource/transport/host - transport_ibverbs.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 11.1 % 1602 178
Test Date: 2026-07-28 12:11:00 Functions: 18.3 % 120 22

            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 <arpa/inet.h>
      12              : #include <securec.h>
      13              : #include <string>
      14              : #include "network/hccp_common.h"
      15              : #include "device_capacity.h"
      16              : #include "network_manager_pub.h"
      17              : #include "adapter_rts.h"
      18              : #include "externalinput_pub.h"
      19              : #include "hccl_network.h"
      20              : #include "externalinput.h"
      21              : #include "../host/transport_ibverbs.h"
      22              : 
      23              : // 混合模式(RoCE Cross-Mode)公共类型定义
      24              : #include "../../../../base_comm/resources/endpoint_pairs/channels/host/exchange_data_format.h"
      25              : 
      26              : using namespace std;
      27              : constexpr u32 RDMA_QP_EXPECT_STATUS_PAUSE = 5;
      28              : constexpr u32 RDMA_QP_EXPECT_STATUS_CONNECTED = 1;
      29              : 
      30              : namespace hccl {
      31              : std::array<DeviceMem, MAX_MODULE_DEVICE_NUM> TransportIbverbs::notifyValueMem_;
      32              : std::array<std::mutex, MAX_MODULE_DEVICE_NUM> TransportIbverbs::notifyValueMutex_;
      33              : std::array<Referenced, MAX_MODULE_DEVICE_NUM> TransportIbverbs::instanceRef_;
      34              : UniversalConcurrentMap<u64, TransportIbverbs*> TransportIbverbs::g_qpn2IbversLinkMap_;
      35              : bool TransportIbverbs::g_flag = false;
      36              : bool TransportIbverbs::g_isSupCqeErrInfoListConfig = false;
      37              : u32 TransportIbverbs::cqeErrQpn_ = 0;
      38              : 
      39              : constexpr u32 CQE_ARRAY_SIZE = 128;
      40              : constexpr u32 DEV_PHY_ID_BIT = 32;
      41              : 
      42              : constexpr u32 WQE_RESERVE_LENGTH = 4;
      43              : 
      44              : constexpr u32 NOTIFY_VA_ALIGN_EIGHT = 8; // notifyVa地址8byte对齐
      45              : 
      46           23 : TransportIbverbs::TransportIbverbs(DispatcherPub *dispatcher,
      47              :                                    const std::unique_ptr<NotifyPool> &notifyPool,
      48              :                                    MachinePara &machinePara,
      49           23 :                                    std::chrono::milliseconds timeout)
      50              :     : TransportNet(dispatcher, notifyPool, machinePara, timeout),
      51           23 :       qpsPerConnection_(1), notifySize_(0), ackNotify_(nullptr), dataAckNotify_(nullptr),
      52           23 :       access_(RA_ACCESS_LOCAL_WRITE | RA_ACCESS_REMOTE_WRITE | RA_ACCESS_REMOTE_READ),
      53           23 :       workFlowMode_(HcclWorkflowMode::HCCL_WORKFLOW_MODE_OPS_KERNEL_INFO_LIB),
      54           46 :       sqeCounter_(0), currentQP_(0), qpMode_(machinePara.qpMode)
      55              : {
      56           23 :     dataNotify_ = nullptr;
      57           23 :     if (machinePara_.deviceLogicId >= 0 && (static_cast<u32>(machinePara_.deviceLogicId) < MAX_MODULE_DEVICE_NUM)) {
      58           23 :         instanceRef_[machinePara_.deviceLogicId].Ref();
      59              :     }
      60           23 : }
      61              : 
      62           23 : TransportIbverbs::~TransportIbverbs()
      63              : {
      64           23 :     HCCL_DEBUG("~TransportIbverbs Enter!");
      65              : 
      66           23 :     (void)DeInit();
      67              : 
      68           23 :     if (machinePara_.deviceLogicId >= 0 && (static_cast<u32>(machinePara_.deviceLogicId) < MAX_MODULE_DEVICE_NUM)) {
      69           23 :         if ( instanceRef_[machinePara_.deviceLogicId].Unref() == 0) {
      70            3 :             std::unique_lock<std::mutex> lock(notifyValueMutex_[machinePara_.deviceLogicId]);
      71            3 :             notifyValueMem_[machinePara_.deviceLogicId].free();
      72            3 :         }
      73              :     }
      74           23 :     HCCL_DEBUG("~TransportIbverbs Success!");
      75           23 : }
      76              : 
      77           34 : HcclResult TransportIbverbs::DeInit()
      78              : {
      79           34 :     (void)DeRegMR();
      80              : 
      81           34 :     (void)DestroySignal();
      82              : 
      83           34 :     (void)DestroyQP();
      84              : 
      85           34 :     return HCCL_SUCCESS;
      86              : }
      87              : 
      88            0 : HcclResult TransportIbverbs::DeRegOneMR(QpHandle& qpHandle, MemMsg& memMsg)
      89              : {
      90            0 :     struct MrInfoT mrInfo = {nullptr};
      91            0 :     mrInfo.addr = memMsg.addr;
      92            0 :     HcclResult ret = HrtRaMrDereg(qpHandle, &mrInfo);
      93            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
      94              :         HCCL_ERROR("errNo[0x%016llx] in link lbv, In lbv exp deconstruct, mr dereg failed.",
      95              :             HCCL_ERROR_CODE(ret)), ret);
      96            0 :     return HCCL_SUCCESS;
      97              : }
      98              : 
      99            1 : void TransportIbverbs::DeRegMRForQPhandles(MemMsg& memMsg)
     100              : {
     101            1 :     for (u32 j = 0; j < combineQpHandles_.size(); j++) {
     102            0 :         if (combineQpHandles_[j].qpHandle == nullptr) {
     103            0 :             continue;
     104              :         }
     105            0 :         (void)DeRegOneMR(combineQpHandles_[j].qpHandle, memMsg);
     106              :     } 
     107            1 :     for (u32 j = 0; j < multiCombineQpHandles_.size(); j++) {
     108            0 :         if (multiCombineQpHandles_[j].qpHandle == nullptr) {
     109            0 :             continue;
     110              :         }
     111            0 :         (void)DeRegOneMR(multiCombineQpHandles_[j].qpHandle, memMsg);
     112              :     }
     113            1 : }
     114              : 
     115           34 : HcclResult TransportIbverbs::DeRegMR()
     116              : {
     117              :     /* 销毁mr */
     118           34 :     std::map<uintptr_t, s32> addrMap;
     119          578 :     for (s32 i = 0; i < static_cast<s32>(MemType::MEM_TYPE_RESERVED); i++) {
     120          544 :         if (memMsg_[i].mrRegFlag == REG_VALID) {
     121              :             std::pair<std::map<uintptr_t, s32>::iterator, bool> res =
     122            1 :                 addrMap.insert(std::pair<uintptr_t, s32>(reinterpret_cast<uintptr_t>(memMsg_[i].addr), 0));
     123            1 :             if (res.second) {
     124            1 :                 DeRegMRForQPhandles(memMsg_[i]);
     125              :             }
     126              :         }
     127              :     }
     128           34 :     return HCCL_SUCCESS;
     129           34 : }
     130              : 
     131            0 : HcclResult TransportIbverbs::DestroyQP(QpHandle& qpHandle)
     132              : {
     133            0 :     if (qpHandle != nullptr) {
     134            0 :         struct QpAttr attr{};
     135            0 :         CHK_RET(hrtRaGetQpAttr(qpHandle, &attr));
     136              : 
     137            0 :         g_qpn2IbversLinkMap_.Erase(((static_cast<u64>(machinePara_.localDeviceId) << DEV_PHY_ID_BIT) | attr.qpn));
     138              : 
     139            0 :         HcclResult ret = HrtRaQpDestroy(qpHandle);
     140            0 :         if (ret != HCCL_SUCCESS) {
     141            0 :             HCCL_ERROR("errNo[0x%016llx] in link lbv, lbv exp deconstruct, qp destroy failed.",
     142              :                 HCCL_ERROR_CODE(ret));
     143              :         }
     144            0 :         qpHandle = nullptr;
     145              :     }
     146            0 :     return HCCL_SUCCESS;
     147              : }
     148              : 
     149           34 : HcclResult TransportIbverbs::DestroyQP()
     150              : {
     151           34 :     for (u32 i = 0; i < combineQpHandles_.size(); i++) {
     152            0 :         CHK_RET(DestroyQP(combineQpHandles_[i].qpHandle));
     153              :     }
     154           34 :     for (u32 i = 0; i < multiCombineQpHandles_.size(); i++) {
     155            0 :         CHK_RET(DestroyQP(multiCombineQpHandles_[i].qpHandle));
     156              :     }
     157           34 :     return HCCL_SUCCESS;
     158              : }
     159              : 
     160            1 : HcclResult TransportIbverbs::Stop()
     161              : {
     162            1 :     HcclResult ret = hrtRaQpBatchModify(nicRdmaHandle_, &combineQpHandles_[0].qpHandle, combineQpHandles_.size(),
     163              :         RDMA_QP_EXPECT_STATUS_PAUSE);
     164            1 :     if (ret != HCCL_SUCCESS) {
     165            0 :         HCCL_ERROR("errNo[0x%016llx] in link lbv, ra qp modify stop fail.",
     166              :             HCCL_ERROR_CODE(ret));
     167            0 :         return HCCL_E_INTERNAL;
     168              :     }
     169            1 :     return HCCL_SUCCESS;
     170              : }
     171              :  
     172            1 : HcclResult TransportIbverbs::Resume()
     173              : {
     174            1 :     HcclResult ret = hrtRaQpBatchModify(nicRdmaHandle_, &combineQpHandles_[0].qpHandle, combineQpHandles_.size(),
     175              :                                         RDMA_QP_EXPECT_STATUS_CONNECTED);
     176            1 :     if (ret != HCCL_SUCCESS) {
     177            0 :         HCCL_ERROR("errNo[0x%016llx] in link lbv, ra qp modify resume fail.",
     178              :             HCCL_ERROR_CODE(ret));
     179            0 :         return HCCL_E_INTERNAL;
     180              :     }
     181            1 :     return HCCL_SUCCESS;
     182              : }
     183              :  
     184            1 : HcclResult TransportIbverbs::Init()
     185              : {
     186            1 :     HCCL_INFO(
     187              :         "machineType=[%d], serverId=[%s], localDeviceId=[%d], remoteDeviceId=[%d], "\
     188              :         "localRank=[%u], localUserRank=[%u], remoteRank=[%u], remoteUserrank=[%u], "\
     189              :         "deviceType=[%d], inputMem=[%p], outputMem=[%p], isAicpuModeEn[%d], notifyNum[%u], "\
     190              :         "isIndOp[%d], custom exchange data size [%llu], drainEnable[%d]",
     191              :         machinePara_.machineType, machinePara_.serverId.c_str(), machinePara_.localDeviceId,
     192              :         machinePara_.remoteDeviceId, machinePara_.localUserrank, machinePara_.localWorldRank,
     193              :         machinePara_.remoteUserrank, machinePara_.remoteWorldRank,
     194              :         machinePara_.deviceType, machinePara_.inputMem.ptr(), machinePara_.outputMem.ptr(),
     195              :         machinePara_.isAicpuModeEn, machinePara_.notifyNum, machinePara_.isIndOp, 
     196              :         machinePara_.exchangeInfo.size(), machinePara_.drainEnable);
     197            1 :     HcclUs startut = TIME_NOW();
     198              : 
     199            1 :     if (machinePara_.userMemEnable) {
     200            1 :         CHK_SMART_PTR_NULL(machinePara_.inputMem);
     201            0 :         CHK_SMART_PTR_NULL(machinePara_.outputMem);
     202            0 :         CHK_SMART_PTR_NULL(notifyPool_);
     203              :     }
     204              : 
     205            0 :     if (machinePara_.drainEnable) {
     206            0 :         CHK_SMART_PTR_NULL(notifyPool_);
     207              :     }
     208              : 
     209            0 :     CHK_PTR_NULL(dispatcher_);
     210            0 :     CHK_RET(CheckDeviceId());
     211            0 :     CHK_RET(CheckExchangeData());
     212              : 
     213              :     // 上层初始化时保证 machinePara_.sockets 非空
     214            0 :     if (machinePara_.sockets.size() == 0) {
     215            0 :         HCCL_ERROR("machinePara sockets is empty.");
     216            0 :         return HCCL_E_INTERNAL;
     217              :     }
     218            0 :     defaultSocket_ = machinePara_.sockets[0];
     219            0 :     CHK_PTR_NULL(defaultSocket_);
     220              : 
     221            0 :     CHK_RET(hrtGetDeviceType(localDeviceType));
     222            0 :     HCCL_INFO("localDeviceType=[%d], remoteDeviceType=[%d]", localDeviceType, machinePara_.deviceType);
     223            0 :     CHK_RET(GetNicHandle());
     224              : 
     225              :     // 设置linkType
     226            0 :     transportAttr_.linkType = hccl::LinkType::LINK_ROCE;
     227              : 
     228              :     /* 获取当前的连接模式,offline模式或者op base模式 */
     229            0 :     workFlowMode_ = GetWorkflowMode();
     230            0 :     HCCL_INFO("current work mode is [%d]", workFlowMode_);
     231              : 
     232            0 :     CHK_RET(GetNotifySize());
     233              : 
     234              :     /* 创建QP连接 */
     235            0 :     CHK_RET(InitQpConnect());
     236              : 
     237            0 :     HCCL_INFO("linkexp initialization success,Time:%lld us", DURATION_US(TIME_NOW() - startut));
     238              :     
     239            0 :     CHK_RET(GetQpAttr());
     240            0 :     return HCCL_SUCCESS;
     241              : }
     242              : 
     243            0 : HcclResult TransportIbverbs::GetQpAttr()
     244              : {
     245              :     char stackLogBuffer[LOG_TMPBUF_SIZE];
     246            0 :     s32 ret = snprintf_s(stackLogBuffer, LOG_TMPBUF_SIZE, LOG_TMPBUF_SIZE - 1U,
     247              :         "communicator[%s], local rank[%u], ip[%s], remote rank[%u], ip[%s], transporttype[%s]",
     248              :         machinePara_.tag.c_str(), machinePara_.localUserrank, machinePara_.localIpAddr.GetReadableAddress(), 
     249            0 :         machinePara_.remoteUserrank, machinePara_.remoteIpAddr.GetReadableAddress(), GetLinkTypeEnumStr(GetLinkType()).c_str());
     250            0 :     CHK_PRT_RET(ret == -1, HCCL_ERROR("[GetQpAttr]errNo[0x%016llx] sal snprintf_s error", 
     251              :         HCCL_ERROR_CODE(HCCL_E_INTERNAL)), HCCL_E_INTERNAL);
     252            0 :     std::string logInfo = "create hccl transport:" + std::string(stackLogBuffer);
     253            0 :     for (u32 i = 0; i < combineQpHandles_.size(); i++){
     254            0 :         struct QpAttr attr{};
     255            0 :         CHK_RET(hrtRaGetQpAttr(combineQpHandles_[i].qpHandle, &attr));
     256            0 :         HCCL_USER_CRITICAL_LOG("%s, rdma qpn[%u], rdma qp sport[%u], rdma TC[%u], rdma SL[%u]",
     257              :             logInfo.c_str(), attr.qpn, attr.udpSport, machinePara_.tc, machinePara_.sl);
     258              :     }
     259            0 :     if (UseMultiQp()) {
     260            0 :         for (u32 i = 0; i < multiCombineQpHandles_.size(); i++){
     261            0 :             struct QpAttr attr{};
     262            0 :             CHK_RET(hrtRaGetQpAttr(multiCombineQpHandles_[i].qpHandle, &attr));
     263            0 :             HCCL_USER_CRITICAL_LOG("%s, rdma qpn[%u], rdma qp sport[%u], rdma TC[%u], rdma SL[%u]",
     264              :                 logInfo.c_str(), attr.qpn, attr.udpSport, machinePara_.tc, machinePara_.sl);
     265              :         }
     266              :     } 
     267            0 :     return HCCL_SUCCESS;
     268            0 : }
     269              : 
     270            0 : HcclResult TransportIbverbs::GetNotifySize()
     271              : {
     272            0 :     u32 notifySize = 0;
     273            0 :     CHK_RET(hrtGetNotifySize(notifySize));
     274            0 :     notifySize_ = notifySize;
     275            0 :     return HCCL_SUCCESS;
     276              : }
     277              : 
     278            0 : HcclResult TransportIbverbs::IsUseQpCreateWithAttrs(bool &isUseQpCreateWithAttrs, s32 qpMode)
     279              : {
     280            0 :     isUseQpCreateWithAttrs = false;
     281            0 :     if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE) {
     282            0 :         bool is910Bor91093 =
     283            0 :             machinePara_.deviceType == DevType::DEV_TYPE_910B || machinePara_.deviceType == DevType::DEV_TYPE_910_93;
     284            0 :         if (is910Bor91093 && (qpMode == OFFLINE_QP_MODE_EXT || qpMode == OPBASE_QP_MODE_EXT)) {
     285            0 :             isUseQpCreateWithAttrs = true;
     286              :         }
     287              :     }
     288            0 :     return HCCL_SUCCESS;
     289              : }
     290              : 
     291            8 : HcclResult TransportIbverbs::FillExchangeDataTotalSize()
     292              : {
     293            8 :     exchangeDataTotalSize_ = 0;
     294            8 :     exchangeDataTotalSize_ += sizeof(u32);  // 首个内容放qp数量
     295            8 :     if (UseMultiQp()) {
     296            2 :         exchangeDataTotalSize_ += sizeof(u32);  // 再放个MultiQpThreshold
     297              :     }
     298            8 :     if (machinePara_.userMemEnable) {
     299            4 :         exchangeDataTotalSize_ += sizeof(MemMsg) * 2; // 2: output and input mem
     300            4 :         exchangeDataTotalSize_ += sizeof(MemMsg) * 3; // 3: dataNotify_\ackNotify_\dataAckNotify_
     301            4 :         if (UseMultiQp()) {
     302            1 :             exchangeDataTotalSize_ += qpsPerConnection_ * sizeof(MemMsg);  // 多QP下新增协商内容
     303              :         }
     304              :     } 
     305            8 :     if (machinePara_.drainEnable) {
     306            1 :         exchangeDataTotalSize_ += sizeof(MemMsg); // Drain用到了dataNotify_
     307            1 :         exchangeDataTotalSize_ += sizeof(MemMsg); // 本端notify srcmem, 用于Drain
     308              :     }
     309            8 :     if (!isHybridMode_) {
     310            8 :         exchangeDataTotalSize_ += machinePara_.exchangeInfo.size();
     311              :     }
     312              : 
     313              :     // 4.新增notify资源统计
     314              :     // 单qp notify资源大小:1*notifyNum, 多qp notify资源大小:qpNum*notifyNum
     315            8 :     exchangeDataTotalSize_ += qpsPerConnection_*sizeof(MemMsg) * notifyNum_;
     316              : 
     317              :     // 5.新增和对端协商atomic write是否使能
     318            8 :     exchangeDataTotalSize_ += sizeof(u8);
     319              : 
     320            8 :     if(machinePara_.isIndOp) {
     321              :         // 6. userDeviceMem数量\userDeviceMem\userHostMem数量\userHostMem
     322            0 :         exchangeDataTotalSize_ += sizeof(u32);
     323            0 :         exchangeDataTotalSize_ += sizeof(MemMsg)*machinePara_.userDeviceMem.size();
     324            0 :         exchangeDataTotalSize_ += sizeof(u32);
     325            0 :         exchangeDataTotalSize_ += sizeof(MemMsg)*machinePara_.userHostMem.size();
     326              :     }
     327              : 
     328            8 :     HCCL_DEBUG("[TransportIbverbs][FillExchangeDataTotalSize] exchangeDataTotalSize[%llu]", exchangeDataTotalSize_);
     329            8 :     return HCCL_SUCCESS;
     330              : }
     331              : 
     332            0 : HcclResult TransportIbverbs::ConstructExchangeForSend()
     333              : {
     334            0 :     exchangeDataForSend_.resize(exchangeDataTotalSize_);
     335            0 :     u8 *exchangeDataPtr = exchangeDataForSend_.data();
     336            0 :     u64 exchangeDataBlankSize = exchangeDataTotalSize_;
     337              :     // 把qp对数量放在最前头,第一个做检验
     338            0 :     u32 qpNum = UseMultiQp() ? qpsPerConnection_ : 1;
     339            0 :     s32 sRet = memcpy_s(exchangeDataPtr, sizeof(u32), reinterpret_cast<void*>(&qpNum), sizeof(u32));
     340            0 :     CHK_PRT_RET(sRet != EOK,
     341              :         HCCL_ERROR("[Set][LocalMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu],cnt[%zu]",
     342              :         HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(u32), sizeof(u32)), HCCL_E_MEMORY);
     343            0 :     exchangeDataPtr += sizeof(u32);
     344            0 :     exchangeDataBlankSize -= sizeof(u32);
     345              : 
     346            0 :     if (UseMultiQp()) {
     347              :         // 把multiQpThreshold放第二个,第二个做检验
     348            0 :         u32 multiQpThreshold = GetExternalInputMultiQpThreshold();
     349            0 :         sRet = memcpy_s(exchangeDataPtr, sizeof(u32), reinterpret_cast<void *>(&multiQpThreshold), sizeof(u32));
     350            0 :         CHK_PRT_RET(sRet != EOK,
     351              :             HCCL_ERROR(
     352              :                 "[Set][LocalMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu],cnt[%zu]",
     353              :                 HCCL_ERROR_CODE(HCCL_E_MEMORY),
     354              :                 sRet,
     355              :                 sizeof(u32),
     356              :                 sizeof(u32)),
     357              :             HCCL_E_MEMORY);
     358            0 :         exchangeDataPtr += sizeof(u32);
     359            0 :         exchangeDataBlankSize -= sizeof(u32);
     360              :     }
     361              : 
     362            0 :     if (machinePara_.userMemEnable) {
     363            0 :         CHK_RET(RegUserMem(MemType::USER_OUTPUT_MEM, exchangeDataPtr, exchangeDataBlankSize));
     364            0 :         CHK_RET(RegUserMem(MemType::USER_INPUT_MEM, exchangeDataPtr, exchangeDataBlankSize));
     365            0 :         if (machinePara_.isAicpuModeEn) {
     366            0 :             CHK_RET(CreateNotifyBuffer(dataNotify_, MemType::DATA_NOTIFY_MEM,
     367              :                 exchangeDataPtr, exchangeDataBlankSize, NotifyLoadType::DEVICE_NOTIFY));
     368            0 :             CHK_RET(CreateNotifyBuffer(ackNotify_, MemType::ACK_NOTIFY_MEM,
     369              :                 exchangeDataPtr, exchangeDataBlankSize, NotifyLoadType::DEVICE_NOTIFY));
     370            0 :             CHK_RET(CreateNotifyBuffer(dataAckNotify_, MemType::DATA_ACK_NOTIFY_MEM,
     371              :                 exchangeDataPtr, exchangeDataBlankSize, NotifyLoadType::DEVICE_NOTIFY));
     372              :         } else {
     373            0 :             CHK_RET(CreateNotifyBuffer(dataNotify_, MemType::DATA_NOTIFY_MEM, exchangeDataPtr, exchangeDataBlankSize));
     374            0 :             CHK_RET(CreateNotifyBuffer(ackNotify_, MemType::ACK_NOTIFY_MEM, exchangeDataPtr, exchangeDataBlankSize));
     375            0 :             CHK_RET(CreateNotifyBuffer(dataAckNotify_, MemType::DATA_ACK_NOTIFY_MEM,
     376              :                 exchangeDataPtr, exchangeDataBlankSize));
     377              :         }
     378              :     } 
     379            0 :     if (!machinePara_.userMemEnable && machinePara_.drainEnable) {
     380            0 :         if (machinePara_.isAicpuModeEn) {
     381            0 :             CHK_RET(CreateNotifyBuffer(dataNotify_, MemType::DATA_NOTIFY_MEM,
     382              :                 exchangeDataPtr, exchangeDataBlankSize, NotifyLoadType::DEVICE_NOTIFY));
     383              :         } else {
     384            0 :             CHK_RET(CreateNotifyBuffer(dataNotify_, MemType::DATA_NOTIFY_MEM, exchangeDataPtr,
     385              :                 exchangeDataBlankSize));
     386              :         }
     387              :         // Drain操作需读取对端srcmem
     388            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(exchangeDataPtr, exchangeDataBlankSize,
     389              :             reinterpret_cast<void *>(&memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)]), sizeof(MemMsg)));
     390            0 :         exchangeDataPtr += sizeof(MemMsg);
     391            0 :         exchangeDataBlankSize -= sizeof(MemMsg);
     392              :     }
     393            0 :     if (!isHybridMode_) {
     394            0 :         CHK_RET(ConstructExchangeDataForSend(exchangeDataPtr, exchangeDataBlankSize));
     395              :     }
     396            0 :     if (machinePara_.userMemEnable && UseMultiQp()) {
     397            0 :         for (u32 i = 0; i < qpsPerConnection_; i++) {
     398            0 :             std::shared_ptr<LocalIpcNotify> oneNotify;
     399            0 :             if (machinePara_.isAicpuModeEn) {
     400            0 :                 CHK_RET(CreateNotifyBuffer(oneNotify, MemType::MULTI_QP_DATA_NOTIFY_MEM, exchangeDataPtr,
     401              :                     exchangeDataBlankSize, NotifyLoadType::DEVICE_NOTIFY));
     402              :             } else {
     403            0 :                 CHK_RET(CreateNotifyBuffer(oneNotify, MemType::MULTI_QP_DATA_NOTIFY_MEM, exchangeDataPtr,
     404              :                     exchangeDataBlankSize));
     405              :             }
     406            0 :             multiQpDataNotify_.push_back(std::move(oneNotify));
     407            0 :         }
     408              :     }
     409              : 
     410              :     // 创建notify pool资源
     411              :     // 单qp创建1*notifyNum个,多qp创建qpNum*notifyNum个
     412            0 :     for (u32 i = 0; i < qpsPerConnection_; i++) {
     413            0 :         std::vector<std::shared_ptr<LocalIpcNotify>> notifyVec;
     414            0 :         CHK_RET(CreateNotifyVectorBuffer(notifyVec, exchangeDataPtr, exchangeDataBlankSize));
     415            0 :         userMultiQpLocalNotify_.push_back(std::move(notifyVec));
     416            0 :     }
     417              : 
     418            0 :     u8 localEnableAtomicWrite = machinePara_.enableAtomicWrite ? 1 : 0;
     419            0 :     sRet = memcpy_s(exchangeDataPtr, sizeof(u8), reinterpret_cast<void *>(&localEnableAtomicWrite), sizeof(u8));
     420            0 :     CHK_PRT_RET(sRet != EOK,
     421              :         HCCL_ERROR("[Set][LocalMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu], cnt[%zu]",
     422              :             HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(bool), sizeof(bool)), HCCL_E_MEMORY);
     423            0 :     exchangeDataPtr += sizeof(u8);
     424            0 :     exchangeDataBlankSize -= sizeof(u8);
     425              : 
     426            0 :     if (machinePara_.isIndOp) {
     427            0 :         CHK_RET(RegCustomUserMem(exchangeDataPtr, exchangeDataBlankSize));
     428              :     }
     429              : 
     430            0 :     if (exchangeDataBlankSize != 0) {
     431            0 :         HCCL_ERROR("[TransportIbverbs][ConstructExchangeForSend] failed to construct exchange Data \
     432              :             exchangeDataBlankSize[%llu]",
     433              :             exchangeDataBlankSize);
     434            0 :         return HCCL_E_INTERNAL;
     435              :     }
     436              : 
     437            0 :     HCCL_DEBUG("[TransportIbverbs] ConstructExchangeForSend finished.");
     438            0 :     return HCCL_SUCCESS;
     439              : }
     440              : 
     441            0 : HcclResult TransportIbverbs::ParseReceivedExchangeData()
     442              : {
     443            0 :     u8* exchangeDataPtr = exchangeDataForRecv_.data();
     444            0 :     u64 exchangeDataBlankSize = exchangeDataTotalSize_;
     445              : 
     446              :     // 首先解析qp对数量,并作一致性校验
     447            0 :     u32 localQpNum = UseMultiQp() ? qpsPerConnection_ : 1;
     448            0 :     u32 remoteQpNum = 0;
     449            0 :     s32 sRet = memcpy_s(reinterpret_cast<void*>(&remoteQpNum), sizeof(u32), exchangeDataPtr, sizeof(u32));
     450            0 :     CHK_PRT_RET(sRet != EOK,
     451              :         HCCL_ERROR("[Get][RemoteMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu],cnt[%zu]",
     452              :         HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(u32), sizeof(u32)), HCCL_E_MEMORY);
     453            0 :     CHK_PRT_RET(localQpNum != remoteQpNum, HCCL_ERROR("[TransportIbverbs][ParseReceivedExchangeData]"
     454              :         "local qps[%u] not equal to remote qps[%u], rank:local[%u],remote[%u]", localQpNum, remoteQpNum,
     455              :         machinePara_.localUserrank, machinePara_.remoteUserrank), HCCL_E_INTERNAL);
     456            0 :     exchangeDataPtr += sizeof(u32);
     457            0 :     exchangeDataBlankSize -= sizeof(u32);
     458              : 
     459            0 :     if (UseMultiQp()) {
     460              :         // 再解析multiQpThreshold,并作一致性校验
     461            0 :         u32 localmultiQpThreshold = GetExternalInputMultiQpThreshold();
     462            0 :         u32 remotemultiQpThreshold = 0;
     463            0 :         sRet = memcpy_s(reinterpret_cast<void *>(&remotemultiQpThreshold), sizeof(u32), exchangeDataPtr, sizeof(u32));
     464            0 :         CHK_PRT_RET(sRet != EOK,
     465              :             HCCL_ERROR(
     466              :                 "[Get][RemoteMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu],cnt[%zu]",
     467              :                 HCCL_ERROR_CODE(HCCL_E_MEMORY),
     468              :                 sRet,
     469              :                 sizeof(u32),
     470              :                 sizeof(u32)),
     471              :             HCCL_E_MEMORY);
     472            0 :         CHK_PRT_RET(localmultiQpThreshold != remotemultiQpThreshold,
     473              :             HCCL_ERROR("[TransportIbverbs][ParseReceivedExchangeData]"
     474              :                        "local env HCCL_MULTI_QP_THRESHOLD[%u] not equal to remote env HCCL_MULTI_QP_THRESHOLD[%u], "
     475              :                        "rank:local[%u],remote[%u]",
     476              :                 localmultiQpThreshold,
     477              :                 remotemultiQpThreshold,
     478              :                 machinePara_.localUserrank,
     479              :                 machinePara_.remoteUserrank),
     480              :             HCCL_E_INTERNAL);
     481            0 :         exchangeDataPtr += sizeof(u32);
     482            0 :         exchangeDataBlankSize -= sizeof(u32);
     483              :     }
     484              : 
     485            0 :     if (machinePara_.userMemEnable) {
     486            0 :         CHK_RET(GetRemoteAddr(MemType::USER_OUTPUT_MEM, exchangeDataPtr, exchangeDataBlankSize));
     487            0 :         CHK_RET(GetRemoteAddr(MemType::USER_INPUT_MEM, exchangeDataPtr, exchangeDataBlankSize));
     488            0 :         CHK_RET(GetRemoteAddr(MemType::DATA_NOTIFY_MEM, exchangeDataPtr, exchangeDataBlankSize));
     489            0 :         s32 sret = memcpy_s(&remoteDataNotifyMsg_, sizeof(MemMsg),
     490            0 :             &remoteMemMsg_[static_cast<u32>(MemType::DATA_NOTIFY_MEM)], sizeof(MemMsg));
     491            0 :         CHK_PRT_RET(sret != EOK,
     492              :             HCCL_ERROR("[Get][RemoteMem]errNo[0x%016llx] In lbv exp init, memory copy failed. errorno[%d], "
     493              :                     "params:destMaxSize[%zu],count[%zu]",
     494              :             HCCL_ERROR_CODE(HCCL_E_MEMORY), sret, sizeof(MemMsg), sizeof(MemMsg)),
     495              :             HCCL_E_MEMORY);
     496            0 :         CHK_RET(GetRemoteAddr(MemType::ACK_NOTIFY_MEM, exchangeDataPtr, exchangeDataBlankSize));
     497            0 :         CHK_RET(GetRemoteAddr(MemType::DATA_ACK_NOTIFY_MEM, exchangeDataPtr, exchangeDataBlankSize));
     498              :     }
     499            0 :     if (!machinePara_.userMemEnable && machinePara_.drainEnable) {
     500            0 :         CHK_RET(GetRemoteAddr(MemType::DATA_NOTIFY_MEM, exchangeDataPtr, exchangeDataBlankSize));
     501            0 :         CHK_RET(GetRemoteAddr(MemType::NOTIFY_SRC_MEM, exchangeDataPtr, exchangeDataBlankSize));
     502              :     }
     503              : 
     504            0 :     if (!isHybridMode_) {
     505            0 :         CHK_RET(ParseExchangeData(exchangeDataPtr, exchangeDataBlankSize));
     506              :     }
     507              : 
     508            0 :     if (machinePara_.userMemEnable && UseMultiQp()) {
     509            0 :         for (u32 i = 0; i < qpsPerConnection_; i++) {
     510            0 :             CHK_RET(GetRemoteAddr(MemType::MULTI_QP_DATA_NOTIFY_MEM, exchangeDataPtr, exchangeDataBlankSize));
     511              :         }
     512              :     }
     513              : 
     514              :     // 解析远端新增的notify资源,二维vec大小:qpNum*notifyNum
     515            0 :     userMultiQpRemoteNotifyMsg_.resize(qpsPerConnection_);
     516            0 :     for (u32 i = 0; i < qpsPerConnection_; i++) {
     517            0 :         userMultiQpRemoteNotifyMsg_[i].resize(notifyNum_);
     518            0 :         for (u32 j = 0; j < notifyNum_; j++) {
     519            0 :             CHK_RET(GetRemoteNotifyAddr(exchangeDataPtr, exchangeDataBlankSize, userMultiQpRemoteNotifyMsg_[i][j]));
     520              :         }
     521              :     }
     522              : 
     523              :     // 解析远端是否都支持atomic write,仅本端和对端都支持时才使能atomic write
     524            0 :     u8 remoteEnableAtomicWrite = 0;
     525            0 :     sRet = memcpy_s(reinterpret_cast<void *>(&remoteEnableAtomicWrite), sizeof(u8), exchangeDataPtr, sizeof(u8));
     526            0 :     CHK_PRT_RET(sRet != EOK,
     527              :         HCCL_ERROR("[Get][RemoteMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu], cnt[%zu]",
     528              :             HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(bool), sizeof(bool)), HCCL_E_MEMORY);
     529            0 :     useAtomicWrite_ = machinePara_.enableAtomicWrite && (remoteEnableAtomicWrite != 0);
     530            0 :     HCCL_INFO("atomic write enable only when both the local and remote support, local[%d], remote[%d], result[%d]",
     531              :         machinePara_.enableAtomicWrite, remoteEnableAtomicWrite, useAtomicWrite_);
     532            0 :     exchangeDataPtr += sizeof(u8);
     533            0 :     exchangeDataBlankSize -= sizeof(u8);
     534              : 
     535            0 :     if (machinePara_.isIndOp) {
     536            0 :         CHK_RET(GetIndOpRemoteAddr(exchangeDataPtr, exchangeDataBlankSize));
     537              :     }
     538              : 
     539            0 :     if (exchangeDataBlankSize != 0) {
     540            0 :         HCCL_ERROR("[TransportIbverbs][ParseReceivedExchangeData] failed to Parse exchange Data \
     541              :             exchangeDataBlankSize[%llu]", exchangeDataBlankSize);
     542            0 :         return HCCL_E_INTERNAL;
     543              :     }
     544            0 :     HCCL_DEBUG("Parse Received ExchangeData success!");
     545            0 :     return HCCL_SUCCESS;
     546              : }
     547              : 
     548            0 : void TransportIbverbs::ModifyAtomicWriteAfterReduce(u32 &preWrOpcode, u64 wqeType, u32 &opcode, u32 &immData)
     549              : {
     550            0 :     bool isNotifyWqe = wqeType == static_cast<u64>(WqeType::WQE_TYPE_DATA_NOTIFY) ||
     551            0 :                        wqeType == static_cast<u64>(WqeType::WQE_TYPE_ACK_NOTIFY) ||
     552              :                        wqeType == static_cast<u64>(WqeType::WQE_TYPE_DATA_ACK_NOTIFY);
     553            0 :     if (useAtomicWrite_ && preWrOpcode == RA_WR_RDMA_REDUCE_WRITE && isNotifyWqe) {
     554            0 :         opcode = RA_WR_RDMA_ATOMIC_WRITE;
     555            0 :         immData = machinePara_.isAicpuModeEn ? htobe32(0x1) : 0x1; // aicpu展开时,HCCL直调RoCE驱动,需进行字节序转换
     556              :     }
     557            0 :     HCCL_DEBUG("%s preWrOpcode[%u] useAtomicWrite[%d] wqeType[%d] opcode[0x%x] immdata[%u]",
     558              :         __func__, preWrOpcode, useAtomicWrite_, wqeType, opcode, immData);
     559            0 :     preWrOpcode = opcode;
     560            0 : }
     561              : 
     562            0 : u32 TransportIbverbs::GetQpsPerConnection()
     563              : {
     564            0 :     u32 externalQps = std::max(static_cast<u32>(machinePara_.srcPorts.size()), 1U);
     565            0 :     s32 qpMode = GetQpMode();
     566            0 :     if (GetWorkflowMode() != HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE &&
     567              :         externalQps != HCCL_QPS_PER_CONNECTION_DEFAULT) {
     568            0 :         HCCL_RUN_INFO("HCCL_RDMA_QPS_PER_CONNECTION is set to [%u] but it is not effective in offline mode.",
     569              :             externalQps);
     570            0 :     } else if (qpMode != OPBASE_QP_MODE_EXT && externalQps > 1) {
     571            0 :         HCCL_RUN_INFO("HCCL_RDMA_QPS_PER_CONNECTION is set to [%u] but current devType[%d] does not support multi-QP.",
     572              :             externalQps, machinePara_.deviceType);
     573            0 :         return 1;  // 非单算子模式仅支持单QP, QPS = 1
     574              :     }
     575            0 :     if (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
     576            0 :         return externalQps;  // only work for opbase mode
     577              :     }
     578            0 :     return 1;  // 非单算子模式仅支持单QP, QPS = 1
     579              : }
     580              : 
     581            0 : HcclResult TransportIbverbs::GetNicHandle()
     582              : {
     583            0 :     RaResourceInfo raResourceInfo;
     584            0 :     CHK_RET(NetworkManager::GetInstance(machinePara_.deviceLogicId).GetRaResourceInfo(raResourceInfo));
     585            0 :     std::map<HcclIpAddress, IpSocket> &tmpSocketMap = machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE ?
     586              :         raResourceInfo.nicSocketMap : raResourceInfo.hostNetSocketMap;
     587              :  
     588            0 :     HcclIpAddress localIpAddr = machinePara_.localIpAddr;
     589              :  
     590              :     // 获取 nicRdmaHandle
     591            0 :     auto itSocket = tmpSocketMap.find(localIpAddr);
     592            0 :     if (itSocket == tmpSocketMap.end()) {
     593            0 :         HCCL_ERROR("[Get][NicHandle]In get nic handle, can not find socket handle, handle size[%u], "\
     594              :             "local ip[%s]", tmpSocketMap.size(), localIpAddr.GetReadableAddress());
     595            0 :         return HCCL_E_PARA;
     596              :     }
     597              :  
     598            0 :     nicRdmaHandle_ = itSocket->second.nicRdmaHandle;
     599            0 :     CHK_PTR_NULL(nicRdmaHandle_);
     600              :  
     601            0 :     return HCCL_SUCCESS;
     602            0 : }
     603              : 
     604            0 : inline static void MultiQpAdjustQpCapacity(struct QpExtAttrs &attrs)
     605              : {
     606            0 :     constexpr int multiQpCapacityRatio = 2;
     607            0 :     attrs.qpAttr.cap.max_send_wr /= multiQpCapacityRatio;
     608            0 :     attrs.cqAttr.sendCqDepth /= multiQpCapacityRatio;
     609            0 : }
     610              : 
     611              : // 创建一个QP
     612            0 : HcclResult TransportIbverbs::CreateOneQp(
     613              :     s32 qpMode, u32 qpsPerConnection, QpHandle &qpHandle, AiQpInfo &aiQpInfo, bool useAicpu, u32 udpSport)
     614              : {
     615            0 :     bool isUseQpCreateWithAttrs = false;
     616            0 :     CHK_RET(IsUseQpCreateWithAttrs(isUseQpCreateWithAttrs, qpMode));
     617              :     HcclResult ret;
     618            0 :     std::string useAicpuTitle = useAicpu ? std::string("aicpu ") : std::string("");
     619            0 :     std::string qpInfo = useAicpuTitle + std::string("rank:") + std::to_string(machinePara_.localWorldRank) +
     620            0 :         std::string(",localUserrank:") + std::to_string(machinePara_.localUserrank) +
     621            0 :         std::string(",localIpAddr: ") + std::string(machinePara_.localIpAddr.GetReadableAddress()) +
     622            0 :         std::string(",deviceLogicId:") + std::to_string(machinePara_.deviceLogicId);
     623            0 :     struct QpExtAttrs attrs{};
     624              :     // 判断是否为NORMALQP需要使用qpMode_; hostnic场景的qpmode也是NORMALQP
     625            0 :     if (useAicpu || qpMode_ == QPMode::NORMAL) {
     626            0 :         bool isWorkFlowLib = (workFlowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OPS_KERNEL_INFO_LIB);
     627            0 :         CHK_RET(ConstructQpAttrs(qpMode, attrs, machinePara_.queueDepthAttr, isWorkFlowLib));
     628            0 :         bool isA3Aicpu = machinePara_.isAicpuModeEn && (machinePara_.deviceType == DevType::DEV_TYPE_910_93);
     629            0 :         if (isA3Aicpu && workFlowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE && qpMode == OPBASE_QP_MODE_EXT) {
     630            0 :             attrs.qpAttr.cap.max_send_wr = machinePara_.queueDepthAttr.sqDepth == INVALID_UINT ? AICPU_SQ_CQ_DEPTH : attrs.qpAttr.cap.max_send_wr;
     631            0 :             attrs.cqAttr.sendCqDepth = machinePara_.queueDepthAttr.sendCqDepth == INVALID_UINT ? AICPU_SQ_CQ_DEPTH : attrs.cqAttr.sendCqDepth;
     632              :         }
     633              :         // A3 aicpu图模式使用单个qp, qp深度为socket数量*128
     634            0 :         bool isAicpuLib = machinePara_.isAicpuModeEn &&
     635            0 :                             (machinePara_.deviceType == DevType::DEV_TYPE_910_93) &&
     636            0 :                             (workFlowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OPS_KERNEL_INFO_LIB);
     637            0 :         if (!UseMultiQp() && isAicpuLib) {
     638            0 :             attrs.qpAttr.cap.max_send_wr = machinePara_.sockets.size() * DEFAULT_OFFLINE_MAX_SEND_WR;
     639            0 :         } else if (UseMultiQp()) {
     640            0 :             MultiQpAdjustQpCapacity(attrs);
     641              :         }
     642            0 :         HCCL_DEBUG("qp set max_send_wr %u, socket size %u, isWorkFlowLib %d",
     643              :             attrs.qpAttr.cap.max_send_wr, machinePara_.sockets.size(), isWorkFlowLib);
     644              : 
     645            0 :         attrs.udpSport = udpSport;
     646            0 :         ret = hrtRaAiQpCreate(machinePara_.localDeviceId, nicRdmaHandle_, &attrs, &aiQpInfo, qpHandle);
     647            0 :         HCCL_DEBUG(
     648              :             "aiQpAddr:%llu db_index:%u, sq_index=%u", aiQpInfo.aiQpAddr, aiQpInfo.dbIndex, aiQpInfo.sqIndex);
     649            0 :         qpInfo = qpInfo + std::string(",sendCqDepth:") + std::to_string(attrs.cqAttr.sendCqDepth);
     650            0 :     } else if (!isUseQpCreateWithAttrs && qpsPerConnection == HCCL_QPS_PER_CONNECTION_DEFAULT) {
     651            0 :         ret = HrtRaQpCreate(nicRdmaHandle_, QP_FLAG_RC, qpMode, qpHandle);
     652            0 :     } else if (!isUseQpCreateWithAttrs && qpsPerConnection != HCCL_QPS_PER_CONNECTION_DEFAULT) {
     653            0 :         HCCL_ERROR("qpsPerConnection[%u] is set but qpMode[%d] is not supported", qpsPerConnection, qpMode);
     654            0 :         return HCCL_E_PARA;
     655              :     } else {
     656            0 :         CHK_RET(ConstructQpAttrs(qpMode, attrs, machinePara_.queueDepthAttr));
     657            0 :         if (machinePara_.deviceType == DevType::DEV_TYPE_910_93 && !machinePara_.isAicpuModeEn && workFlowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE && qpMode == OPBASE_QP_MODE_EXT) {
     658            0 :             attrs.qpAttr.cap.max_send_wr = machinePara_.queueDepthAttr.sqDepth == INVALID_UINT ? HOST_SQ_CQ_DEPTH : attrs.qpAttr.cap.max_send_wr;
     659            0 :             attrs.cqAttr.sendCqDepth = machinePara_.queueDepthAttr.sendCqDepth == INVALID_UINT ? HOST_SQ_CQ_DEPTH : attrs.cqAttr.sendCqDepth;
     660              :         }
     661            0 :         if (UseMultiQp()) {
     662            0 :             MultiQpAdjustQpCapacity(attrs);
     663              :         }
     664            0 :         attrs.udpSport = udpSport;
     665            0 :         ret = hrtRaQpCreateWithAttrs(nicRdmaHandle_, &attrs, qpHandle);
     666            0 :         qpInfo = qpInfo + std::string(",sendCqDepth:") + std::to_string(attrs.cqAttr.sendCqDepth);
     667              :     }
     668              :     
     669            0 :     RPT_ENV_ERR(ret != 0 || (qpHandle == nullptr), "EI0007", vector<string>({ "resource_type", "resource_info" }),
     670              :         vector<string>({ "qp", "CreateOneQp" }));
     671              : 
     672            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[%s][%s]create qp failed, localDeviceId[%d], qpMode[%d]",
     673              :         LOG_KEYWORDS_INIT_GROUP.c_str(), LOG_KEYWORDS_RESOURCE.c_str(), machinePara_.localDeviceId, qpMode),
     674              :         HCCL_E_ROCE_CONNECT);
     675              : 
     676              :     // 表示没有通过config配置,则使用环境变量配置
     677            0 :     CHK_RET(SetQpAttrQos(qpHandle, machinePara_.tc, machinePara_.sl));
     678              :     // 配置RDMA Timeout时间
     679            0 :     CHK_RET(SetQpAttrTimeOut(qpHandle));
     680              :     // 配置RDMA Retry Cnt重传次数
     681            0 :     CHK_RET(SetQpAttrRetryCnt(qpHandle));
     682              :     // qpn map 插入
     683            0 :     struct QpAttr attr{} ;
     684            0 :     CHK_RET(hrtRaGetQpAttr(qpHandle, &attr));
     685              : 
     686            0 :     g_qpn2IbversLinkMap_.Emplace(((static_cast<u64>(machinePara_.localDeviceId) << DEV_PHY_ID_BIT) | attr.qpn), this);
     687              : 
     688            0 :     HCCL_DEBUG("ra qp create success, use input udpSport[%u].", udpSport);
     689            0 :     return HCCL_SUCCESS;
     690            0 : }
     691              : 
     692            0 : HcclResult TransportIbverbs::CreateSingleQp(s32 qpMode) // 根据socket个数创建QP(下沉模板不够用多QP)
     693              : {
     694            0 :     u32 socketNum = 1;
     695              :     // A3 aicpu图模式只使用1个qp,qp深度为socketNum*128,最大不超过32K
     696            0 :     bool isAicpuLib = machinePara_.isAicpuModeEn &&
     697            0 :                         (machinePara_.deviceType == DevType::DEV_TYPE_910_93) &&
     698            0 :                         (workFlowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OPS_KERNEL_INFO_LIB);
     699            0 :     if (!UseMultiQp() && !isAicpuLib) {
     700            0 :         socketNum = machinePara_.sockets.size();
     701              :     }
     702              :     // 原来是 machinePara_.socketFdHandles 换成 machinePara_.sockets
     703            0 :     for (u32 i = 0; i < socketNum; i++) {
     704            0 :         QpHandle qpHandle = nullptr;
     705            0 :         u32 udpSport = machinePara_.srcPorts.empty()? 0 : machinePara_.srcPorts[0];
     706            0 :         CHK_RET(CreateOneQp(qpMode, HCCL_QPS_PER_CONNECTION_DEFAULT, qpHandle, combineAiQpInfo_.aiQpInfo,
     707              :             machinePara_.isAicpuModeEn, udpSport));
     708            0 :         CombineQpHandle tmpCombineQpHandle;
     709            0 :         tmpCombineQpHandle.qpHandle = qpHandle;
     710            0 :         combineQpHandles_.push_back(tmpCombineQpHandle);
     711              :     }
     712            0 :     return HCCL_SUCCESS;
     713              : }
     714              : 
     715            0 : HcclResult TransportIbverbs::CreateMultiQp(s32 qpMode, u32 qpsPerConnection)
     716              : {
     717              :     // 配置了多qp源端口号时的处理流程
     718            0 :     if (machinePara_.srcPorts.size() > 0) {
     719            0 :         HCCL_DEBUG("[TransportIbverbs][CreateMultiQp]use Multi qp create qps.");
     720              :         // 创建qp
     721            0 :         for (const auto &port : machinePara_.srcPorts) {
     722            0 :             QpHandle qpHandle = nullptr;
     723            0 :             AiQpInfo tmpAiQpInfo{};
     724            0 :             CHK_RET(CreateOneQp(qpMode,
     725              :                 qpsPerConnection,
     726              :                 qpHandle,
     727              :                 tmpAiQpInfo,
     728              :                 machinePara_.isAicpuModeEn, port));
     729            0 :             multiCombineQpHandles_.push_back(CombineQpHandle(qpHandle));
     730            0 :             combineAiQpInfos_.push_back(CombineQpInfo(tmpAiQpInfo));
     731              :         }
     732              :     }
     733            0 :     HCCL_DEBUG("ra multi-qp creation success.");
     734            0 :     return HCCL_SUCCESS;
     735              : }
     736              : 
     737           12 : s32 TransportIbverbs::GetQpMode()
     738              : {
     739           12 :     s32 qpMode = NORMAL_QP_MODE;
     740              : 
     741           12 :     if (qpMode_ == QPMode::NORMAL) {
     742            0 :         return qpMode;
     743              :     }
     744              : 
     745           12 :     if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE) {
     746           12 :         if (workFlowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
     747            0 :             qpMode = (machinePara_.deviceType == DevType::DEV_TYPE_910B ||
     748            0 :                 machinePara_.deviceType == DevType::DEV_TYPE_910_93) ? OPBASE_QP_MODE_EXT : OPBASE_QP_MODE;
     749              :             // isCapture需要创建下沉QP
     750            0 :             qpMode = (qpMode == OPBASE_QP_MODE_EXT && qpMode_ == QPMode::OFFLOAD) ? OFFLINE_QP_MODE_EXT : qpMode;
     751            0 :             isCapture_ = (qpMode == OFFLINE_QP_MODE_EXT) ? true : false;
     752              :         } else {
     753           12 :             qpMode = (machinePara_.deviceType == DevType::DEV_TYPE_910B ||
     754           12 :                 machinePara_.deviceType == DevType::DEV_TYPE_910_93) ? OFFLINE_QP_MODE_EXT : OFFLINE_QP_MODE;
     755              :         }
     756              :     }
     757           12 :     if (machinePara_.isAicpuModeEn) {
     758            3 :         qpMode = (machinePara_.deviceType == DevType::DEV_TYPE_910B ||
     759            3 :             machinePara_.deviceType == DevType::DEV_TYPE_910_93) ? OPBASE_QP_MODE_EXT : OPBASE_QP_MODE;
     760              :     }
     761           12 :     return qpMode;
     762              : }
     763              : 
     764           12 : bool TransportIbverbs::UseMultiQp()
     765              : {
     766           12 :     s32 qpMode = GetQpMode();
     767           12 :     HCCL_DEBUG("[TransportIbverbs]UseMultiQp qpsPerConnection[%u]", qpsPerConnection_);
     768           12 :     if (qpMode == OPBASE_QP_MODE_EXT && qpsPerConnection_ > 1) {
     769            3 :         return true;
     770              :     }
     771            9 :     return false;
     772              : }
     773              : 
     774            0 : HcclResult TransportIbverbs::CreateQp()
     775              : {
     776            0 :     s32 qpMode = GetQpMode();
     777            0 :     HCCL_DEBUG("[TransportIbverbs][CreateQp] QpMode[%u]", qpMode);
     778            0 :     CHK_RET(CreateSingleQp(qpMode));
     779            0 :     if (UseMultiQp()) {
     780            0 :         HCCL_DEBUG("[TransportIbverbs]Create MultiQP begin");
     781            0 :         CHK_RET(CreateMultiQp(qpMode, qpsPerConnection_));
     782              :     }
     783            0 :     HCCL_DEBUG("ra qp create %u qp success.", combineQpHandles_.size());
     784            0 :     return HCCL_SUCCESS;
     785              : }
     786              : 
     787            0 : HcclResult TransportIbverbs::InitQpConnect()
     788              : {
     789              :     /* 创建QP操作句柄 */
     790            0 :     qpsPerConnection_ = GetQpsPerConnection();
     791              : 
     792            0 :     CHK_RET(ExchangeCapabilityHybrid());
     793              : 
     794            0 :     CHK_RET(CreateQp());
     795              : 
     796            0 :     CHK_RET(FillExchangeDataTotalSize());
     797              : 
     798              :     // 注册notify 内存信息
     799            0 :     CHK_RET(CreateNotifyValueBuffer());
     800              : 
     801            0 :     CHK_RET(ConstructExchangeForSend());
     802            0 :     HCCL_DEBUG("[TransportIbverbs] resource create done exchangeDataTotalSize_[%llu]", exchangeDataTotalSize_);
     803              : 
     804            0 :     HcclResult ret = defaultSocket_->Send(exchangeDataForSend_.data(), exchangeDataTotalSize_);
     805            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     806              :         HCCL_ERROR("[TransportIbverbs][InitQpConnect] failed to send exchangeData exchangeDataTotalSize[%llu], "
     807              :             "custom exchange data size [%llu].", exchangeDataTotalSize_, machinePara_.exchangeInfo.size()), ret);
     808            0 :     HCCL_DEBUG("[TransportIbverbs]Seocket Send finished, exchangeDataTotalSize[%llu]", exchangeDataTotalSize_);
     809              : 
     810            0 :     exchangeDataForRecv_.resize(exchangeDataTotalSize_);
     811            0 :     ret = defaultSocket_->Recv(exchangeDataForRecv_.data(), exchangeDataTotalSize_);
     812            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     813              :         HCCL_ERROR("[TransportIbverbs][InitQpConnect] failed to recv exchangeData exchangeDataTotalSize[%llu], "
     814              :             "custom exchange data size [%llu].", exchangeDataTotalSize_, machinePara_.exchangeInfo.size()), ret);
     815              : 
     816            0 :     HCCL_DEBUG("[TransportIbverbs][Init] Socket Data Recved");
     817              : 
     818            0 :     CHK_RET(ParseReceivedExchangeData());
     819              : 
     820              :     // 连接Qp
     821            0 :     CHK_RET(ConnectQp());
     822            0 :     HCCL_INFO("In link ibv, qp status has ready");
     823            0 :     return HCCL_SUCCESS;
     824              : }
     825              : 
     826            0 : HcclResult TransportIbverbs::ConnectSingleQp(std::function<bool()> needStop)
     827              : {
     828              :     // QP建链
     829            0 :     for (u32 i = 0; i < combineQpHandles_.size(); i++) {
     830            0 :         CHK_RET(HrtRaQpConnectAsync(combineQpHandles_[i].qpHandle, machinePara_.sockets[i]->GetFdHandle(), needStop));
     831              :     }
     832              :     // 查询QP建链是否成功
     833            0 :     s32 qpStatus = 0;
     834            0 :     s32 raRet = 0;
     835            0 :     auto startTime = std::chrono::steady_clock::now();
     836            0 :     HCCL_INFO("In link ibv, waiting for qp status ready...");
     837            0 :     for (u32 i = 0; i < combineQpHandles_.size(); i++) {
     838              :         while (true) {
     839            0 :             CHK_PRT_RET(needStop(), HCCL_ERROR("Terminating operation due to external request"), HCCL_E_INTERNAL);
     840              : 
     841            0 :             if ((std::chrono::steady_clock::now() - startTime) >= timeout_) {
     842            0 :                 HCCL_ERROR("[Connect][Qp]get qp status timeout_=%lld, qp_status=%d", timeout_, qpStatus);
     843            0 :                 return HCCL_E_TIMEOUT;
     844              :             }
     845            0 :             raRet = hrtGetRaQpStatus(combineQpHandles_[i].qpHandle, &qpStatus);
     846            0 :             if ((!raRet) && (qpStatus == 1)) { // 为1时,qp 建链成功
     847            0 :                 HCCL_INFO("In link ibv, %u of %u QP get status success.", (i + 1), combineQpHandles_.size());
     848            0 :                 break;
     849              :             } else {
     850              :                 // qp建链需要时间,获取qp状态直至超时
     851            0 :                 SaluSleep(WAIT_US_COUNT);
     852              :             }
     853              :         }
     854              :     }
     855            0 :     return HCCL_SUCCESS;
     856              : }
     857              : 
     858            0 : HcclResult TransportIbverbs::ConnectMultiQp(u32 qpsPerConnection, std::function<bool()> needStop)
     859              : {
     860              :     // 多QP下,复用同一个socket handle来modify QP, 此时需要串行创建
     861            0 :     if (machinePara_.sockets.size() != 2) {  // 2:多QP下需要一个额外的Socket来做QP状态迁移同步
     862            0 :         return HCCL_E_INTERNAL;
     863              :     }
     864            0 :     for (u32 i = 0; i < qpsPerConnection; i++) {
     865              :         // QP建链
     866            0 :         u8 localQpConnectReady = 1;
     867            0 :         u8 remoteQpConnectReady = 0;
     868            0 :         CHK_RET(machinePara_.sockets[1]->Send(&localQpConnectReady, 1));
     869            0 :         CHK_RET(machinePara_.sockets[1]->Recv(&remoteQpConnectReady, 1));
     870            0 :         std::string aicpu = machinePara_.isAicpuModeEn ? "aicpu" : "";
     871            0 :         CHK_PRT_RET(remoteQpConnectReady != localQpConnectReady,
     872              :             HCCL_ERROR("[TransportIbverbs] %s multi Qp Connected checking failed! %u of %u QP",
     873              :             aicpu.c_str(), (i + 1), qpsPerConnection), HCCL_E_NETWORK);
     874            0 :         CHK_RET(HrtRaQpConnectAsync(multiCombineQpHandles_[i].qpHandle, machinePara_.sockets[0]->GetFdHandle(), needStop));
     875              :         // 查询QP建链是否成功
     876            0 :         s32 qpStatus = 0;
     877            0 :         s32 raRet = 0;
     878            0 :         auto startTime = std::chrono::steady_clock::now();
     879            0 :         HCCL_INFO("In link ibv, waiting for qp status ready... %u of %u %s QP",
     880              :             (i + 1), multiCombineQpHandles_.size(), aicpu.c_str());
     881              :         while (true) {
     882            0 :             if ((std::chrono::steady_clock::now() - startTime) >= timeout_) {
     883            0 :                 HCCL_ERROR("[Connect][Qp]get qp status timeout_=%lld, qp_status=%d, index[%u]",
     884              :                     timeout_, qpStatus, i);
     885            0 :                 return HCCL_E_TIMEOUT;
     886              :             }
     887            0 :             raRet = hrtGetRaQpStatus(multiCombineQpHandles_[i].qpHandle, &qpStatus);
     888            0 :             if ((!raRet) && (qpStatus == 1)) { // 为1时,qp 建链成功
     889            0 :                 HCCL_INFO("In link ibv, %u of %u %s QP get status success.",
     890              :                     (i + 1), multiCombineQpHandles_.size(), aicpu.c_str());
     891            0 :                 break;
     892              :             } else {
     893              :                 // qp建链需要时间,获取qp状态直至超时
     894            0 :                 SaluSleep(WAIT_US_COUNT);
     895              :             }
     896              :         }
     897            0 :     }
     898            0 :     return HCCL_SUCCESS;
     899              : }
     900              : 
     901            0 : HcclResult TransportIbverbs::ConnectQp()
     902              : {
     903            0 :     CHK_RET(ConnectSingleQp([this]() -> bool { return this->GetStopFlag(); }));
     904            0 :     if (UseMultiQp()) {
     905            0 :         CHK_RET(ConnectMultiQp(qpsPerConnection_, [this]() -> bool { return this->GetStopFlag(); }));
     906              :     }
     907            0 :     return HCCL_SUCCESS;
     908              : }
     909              : 
     910            1 : HcclResult TransportIbverbs::Fence()
     911              : {
     912            1 :     fence_ = true;
     913            1 :     return HCCL_SUCCESS;
     914              : }
     915              : 
     916            1 : HcclResult TransportIbverbs::AddWqeList(void *dstMemPtr, const void *srcMemPtr, u64 srcMemSize,
     917              :     WqeType wqeType, WrAuxInfo &aux, std::vector<WqeInfo> &wqeInfoVec)
     918              : {
     919            1 :     WqeInfo wqeInfoTmp;
     920              : 
     921            1 :     wqeInfoTmp.wqeData.dstAddr = static_cast<u64>(reinterpret_cast<uintptr_t>(dstMemPtr));
     922            1 :     wqeInfoTmp.wqeData.sendFlags = fence_ ? (RA_SEND_SIGNALED | RA_SEND_FENCE) : RA_SEND_SIGNALED;
     923            1 :     fence_ = false;
     924            1 :     wqeInfoTmp.wqeData.memList.addr = static_cast<u64>(reinterpret_cast<uintptr_t>(srcMemPtr));
     925            1 :     wqeInfoTmp.wqeData.memList.len = srcMemSize;
     926            1 :     wqeInfoTmp.wqeData.memList.lkey = 0;
     927              : 
     928            1 :     switch (wqeType) {
     929            0 :         case WqeType::WQE_TYPE_DATA:
     930              :         case WqeType::WQE_TYPE_DATA_NOTIFY:
     931              :         case WqeType::WQE_TYPE_ACK_NOTIFY:
     932              :         case WqeType::WQE_TYPE_DATA_ACK_NOTIFY:
     933              :         case WqeType::WQE_TYPE_DATA_WITH_NOTIFY:
     934            0 :             wqeInfoTmp.wqeData.op = RA_WR_RDMA_WRITE;
     935            0 :             wqeInfoTmp.wqeType = static_cast<u64>(wqeType);
     936            0 :             break;
     937            0 :         case WqeType::WQE_TYPE_DATA_WITH_REDUCE:
     938            0 :             wqeInfoTmp.wqeData.op = RA_WR_RDMA_REDUCE_WRITE;
     939            0 :             wqeInfoTmp.wqeData.aux = aux;
     940              :             // REDUCE WRITE 作为特殊的DATA
     941            0 :             wqeInfoTmp.wqeType = static_cast<u64>(WqeType::WQE_TYPE_DATA);
     942            0 :             break;
     943            1 :         case WqeType::WQE_TYPE_READ_DATA:
     944            1 :             wqeInfoTmp.wqeData.op = RA_WR_RDMA_READ;
     945            1 :             wqeInfoTmp.wqeType = static_cast<u64>(wqeType);
     946            1 :             break;
     947            0 :         default:
     948            0 :             HCCL_ERROR("error wqeType[%d]", wqeType);
     949            0 :             return HCCL_E_INTERNAL;
     950              :     }
     951            1 :     CHK_RET(GetWqeDataOffsetAndNotifyId(wqeType, wqeInfoTmp.wqeDataOffset, wqeInfoTmp.notifyId));
     952              : 
     953            1 :     wqeInfoVec.push_back(wqeInfoTmp);
     954            1 :     return HCCL_SUCCESS;
     955              : }
     956              : 
     957            0 : HcclResult TransportIbverbs::ConstructPayLoadWqe(void *dstMemPtr, const void *src, u64 len,
     958              :     WqeType wqeType, WrAuxInfo &aux, std::vector<WqeInfo>& wqeInfoVec, u32 txSendDataTimes)
     959              : {
     960              :     HcclResult ret;
     961              :     // 发送数据Wqe
     962            0 :     for (u32 txSendDataIdx = 0; txSendDataIdx < txSendDataTimes; txSendDataIdx++) {
     963            0 :         u64 txSendDataOffset = txSendDataIdx * RDMA_SEND_MAX_SIZE;
     964            0 :         u64 txSendDataSize = (txSendDataIdx == (txSendDataTimes - 1)) ? len - txSendDataOffset : RDMA_SEND_MAX_SIZE;
     965              : 
     966            0 :         void* txdstMemPtr = reinterpret_cast<void *>(reinterpret_cast<char *>(dstMemPtr) +
     967              :             txSendDataOffset);
     968              : 
     969            0 :         const void* txsrcMemPtr = reinterpret_cast<const void *>(reinterpret_cast<const char *>(src) +
     970              :             txSendDataOffset);
     971            0 :         ret = AddWqeList(txdstMemPtr, txsrcMemPtr, txSendDataSize, wqeType, aux, wqeInfoVec);
     972            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
     973              :             HCCL_ERROR("[TransportIbverbs][TxAsync]errNo[0x%016llx] In lbv exp, add wqe list failed."\
     974              :                 "srcMemSize[%llu Byte]", HCCL_ERROR_CODE(ret), txSendDataSize), ret);
     975              :     }
     976              : 
     977            0 :     return HCCL_SUCCESS;
     978              : }
     979              : 
     980            0 : HcclResult TransportIbverbs::TxPayLoad(UserMemType dstMemType, u64 dstOffset, const void *src, u64 len,
     981              :     WqeType wqeType, WrAuxInfo &aux, std::vector<WqeInfo>& wqeInfoVec)
     982              : {
     983            0 :     void *dstMemPtr = nullptr;
     984            0 :     u64 dstMemSize = 0;
     985              :     // 为保证单算子下不同数据量下子图的结构相同,zero byte message 时也需要下发task
     986            0 :     u32 txSendDataTimes = (len == 0) ? 1 : (len + RDMA_SEND_MAX_SIZE - 1) / RDMA_SEND_MAX_SIZE;
     987            0 :     CHK_RET(GetMemInfo(dstMemType, &dstMemPtr, &dstMemSize));
     988              : 
     989            0 :     if (dstOffset > dstMemSize) {
     990            0 :         HCCL_ERROR("[TransportIbverbs][TxAsync]dst_mem_type=%d, dst_mem_ptr=%p, dst_offset=%llu, dst_mem_size=%llu Byte",
     991              :             dstMemType, dstMemPtr, dstOffset, dstMemSize);
     992            0 :         return HCCL_E_INTERNAL;
     993              :     }
     994              : 
     995            0 :     dstMemPtr = reinterpret_cast<void *>(reinterpret_cast<char *>(dstMemPtr) + dstOffset);
     996            0 :     CHK_RET(ConstructPayLoadWqe(dstMemPtr, src, len, wqeType, aux, wqeInfoVec, txSendDataTimes));
     997              : 
     998            0 :     return HCCL_SUCCESS;
     999              : }
    1000              : 
    1001            0 : HcclResult TransportIbverbs::TxAsync(UserMemType dstMemType, u64 dstOffset,
    1002              :                                      const void *src, u64 len, Stream &stream)
    1003              : {
    1004            0 :     std::vector<WqeInfo> wqeInfoVec;
    1005            0 :     wqeInfoVec.reserve(WQE_RESERVE_LENGTH);
    1006            0 :     struct WrAuxInfo aux = {0};
    1007            0 :     HCCL_DEBUG("TX src[%p] len[%llu] dstOffset[%llu]", src, len, dstOffset);
    1008              : 
    1009            0 :     if (src != nullptr) {
    1010            0 :         CHK_RET(TxPayLoad(dstMemType, dstOffset, src, len, WqeType::WQE_TYPE_DATA, aux, wqeInfoVec));
    1011              :     }
    1012              : 
    1013            0 :     CHK_RET(TxSendDataAndNotify(wqeInfoVec, stream, GetUseOneDoorbellValue()));
    1014            0 :     return HCCL_SUCCESS;
    1015            0 : }
    1016              : 
    1017            0 : HcclResult TransportIbverbs::TxWithReduce(UserMemType dstMemType, u64 dstOffset, const void *src, u64 len,
    1018              :                                           const HcclDataType datatype, HcclReduceOp redOp, Stream &stream)
    1019              : {
    1020            0 :     std::vector<WqeInfo> wqeInfoVec;
    1021            0 :     wqeInfoVec.reserve(WQE_RESERVE_LENGTH);
    1022            0 :     struct WrAuxInfo aux = {0};
    1023            0 :     aux.dataType = RDMA_REDUCE_DATA_TYPE_TABLE[datatype];
    1024            0 :     aux.reduceType = RDMA_REDUCE_OP_TYPE_TABLE[redOp];
    1025            0 :     if (aux.dataType == static_cast<uint8_t>(RdmaReduceDataType::RDMA_REDUCE_DATA_INVALID) ||
    1026            0 :         aux.reduceType == static_cast<uint8_t>(RdmaReduceOpType::RDMA_REDUCE_OP_INVALID)) {
    1027            0 :         HCCL_ERROR("unsupported data type [%s] or Reduce type [%s]",
    1028              :             GetDataTypeEnumStr(datatype).c_str(), GetReduceOpEnumStr(redOp).c_str());
    1029            0 :         return HCCL_E_INTERNAL;
    1030              :     }
    1031              : 
    1032            0 :     CHK_PTR_NULL(src);
    1033            0 :     CHK_RET(TxPayLoad(dstMemType, dstOffset, src, len, WqeType::WQE_TYPE_DATA_WITH_REDUCE, aux, wqeInfoVec));
    1034              : 
    1035            0 :     CHK_RET(TxSendDataAndNotify(wqeInfoVec, stream, GetUseOneDoorbellValue()));
    1036            0 :     return HCCL_SUCCESS;
    1037            0 : }
    1038              : 
    1039            0 : HcclResult TransportIbverbs::TxWithReduce(const std::vector<TxMemoryInfo> &txWithReduceMems,
    1040              :     const HcclDataType datatype, HcclReduceOp redOp, Stream &stream)
    1041              : {
    1042            0 :     std::vector<WqeInfo> wqeInfoVec;
    1043            0 :     wqeInfoVec.reserve(WQE_RESERVE_LENGTH);
    1044            0 :     struct WrAuxInfo aux = {0};
    1045            0 :     aux.dataType = RDMA_REDUCE_DATA_TYPE_TABLE[datatype];
    1046            0 :     aux.reduceType = RDMA_REDUCE_OP_TYPE_TABLE[redOp];
    1047            0 :     if (aux.dataType == static_cast<uint8_t>(RdmaReduceDataType::RDMA_REDUCE_DATA_INVALID) ||
    1048            0 :         aux.reduceType == static_cast<uint8_t>(RdmaReduceOpType::RDMA_REDUCE_OP_INVALID)) {
    1049            0 :         HCCL_ERROR("unsupported data type [%s] or Reduce type [%s]",
    1050              :             GetDataTypeEnumStr(datatype).c_str(), GetReduceOpEnumStr(redOp).c_str());
    1051            0 :         return HCCL_E_INTERNAL;
    1052              :     }
    1053              : 
    1054            0 :     for (const TxMemoryInfo &txWithReduceMem : txWithReduceMems) {
    1055            0 :         CHK_RET(TxPayLoad(txWithReduceMem.dstMemType, txWithReduceMem.dstOffset, txWithReduceMem.src,
    1056              :             txWithReduceMem.len, WqeType::WQE_TYPE_DATA_WITH_REDUCE, aux, wqeInfoVec));
    1057              :     }
    1058              : 
    1059            0 :     CHK_RET(TxSendDataAndNotify(wqeInfoVec, stream, GetUseOneDoorbellValue()));
    1060            0 :     return HCCL_SUCCESS;
    1061            0 : }
    1062              : 
    1063            0 : bool TransportIbverbs::IsSupportTransportWithReduce()
    1064              : {
    1065            0 :     if (machinePara_.deviceType == DevType::DEV_TYPE_910B || machinePara_.deviceType == DevType::DEV_TYPE_910_93) {
    1066            0 :         return true;
    1067              :     } else {
    1068            0 :         return false;
    1069              :     }
    1070              : }
    1071              : 
    1072              : // 910A1 不支持write with notify; 
    1073              : // 910A2 由于PCIE through 和 write with notify 冲突,所以不支持write with Notify;
    1074            0 : bool TransportIbverbs::IsSupportRdmaNotify()
    1075              : {
    1076            0 :     return false;
    1077              : }
    1078              : 
    1079            1 : bool TransportIbverbs::IsTemplateMode()
    1080              : {
    1081            1 :     if (workFlowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE ||
    1082            1 :         machinePara_.deviceType == DevType::DEV_TYPE_910B ||
    1083            1 :         machinePara_.deviceType == DevType::DEV_TYPE_910_93) {
    1084            0 :             return false;
    1085              :     } else {
    1086            1 :         return true;
    1087              :     }
    1088              : }
    1089              : 
    1090            0 : HcclResult TransportIbverbs::GetIndOpRemoteMemDetails(MemDetails** remoteMem, uint32_t *memNum, HcclMemType memType)
    1091              : {
    1092            0 :     CHK_PRT_RET(remoteMem == nullptr, HCCL_ERROR("[%s] remoteMem is nullptr", __func__), HCCL_E_PARA);
    1093            0 :     CHK_PRT_RET(memNum == nullptr, HCCL_ERROR("[%s] memNum is nullptr", __func__), HCCL_E_PARA);
    1094              :  
    1095            0 :     *remoteMem = nullptr;
    1096            0 :     *memNum = 0;
    1097              :     uint32_t memCount;
    1098            0 :     if (memType == HcclMemType::HCCL_MEM_TYPE_DEVICE) {
    1099            0 :         memCount = remoteUserDeviceMemMsg_.size();
    1100            0 :     } else if (memType == HcclMemType::HCCL_MEM_TYPE_HOST) {
    1101            0 :         memCount = remoteUserHostMemMsg_.size();
    1102              :     } else {
    1103            0 :         HCCL_ERROR("[%s] not support memType[%d]", __func__, memType);
    1104            0 :         return HCCL_E_INTERNAL;
    1105              :     }
    1106            0 :     if (memCount == 0) {
    1107            0 :         HCCL_DEBUG("[%s] No remote memory regions available", __func__);
    1108            0 :         return HCCL_SUCCESS;
    1109              :     }
    1110              :     // 外部需要手动释放内存
    1111            0 :     MemDetails* remoteMemDetails = static_cast<MemDetails*>(malloc(memCount * sizeof(MemDetails)));
    1112            0 :     CHK_PTR_NULL(remoteMemDetails);
    1113            0 :     uint32_t index = 0;
    1114            0 :     if (memType == HcclMemType::HCCL_MEM_TYPE_DEVICE) {
    1115            0 :         for (const auto& msg : remoteUserDeviceMemMsg_) {
    1116            0 :             remoteMemDetails[index].addr = reinterpret_cast<u64>(msg.addr);
    1117            0 :             remoteMemDetails[index].size = msg.len;
    1118            0 :             remoteMemDetails[index].key = msg.lkey;
    1119            0 :             index++;
    1120              :         }
    1121            0 :     } else if (memType == HcclMemType::HCCL_MEM_TYPE_HOST) {
    1122            0 :         for (const auto& msg : remoteUserHostMemMsg_) {
    1123            0 :             remoteMemDetails[index].addr = reinterpret_cast<u64>(msg.addr);
    1124            0 :             remoteMemDetails[index].size = msg.len;
    1125            0 :             remoteMemDetails[index].key = msg.lkey;
    1126            0 :             index++;
    1127              :         }
    1128              :     }
    1129            0 :     *memNum = memCount;
    1130            0 :     *remoteMem = remoteMemDetails;
    1131              :  
    1132            0 :     HCCL_DEBUG("[%s] Successfully returned %u remote memory regions", __func__, index);
    1133            0 :     return HCCL_SUCCESS;
    1134              : }
    1135              : 
    1136            0 : HcclResult TransportIbverbs::GetIndOpRemoteMem(HcclMem **remoteMem, uint32_t *memNum)
    1137              : {
    1138            0 :     CHK_PRT_RET(remoteMem == nullptr, HCCL_ERROR("[GetIndOpRemoteMem] remoteMem is nullptr"), HCCL_E_PARA);
    1139            0 :     CHK_PRT_RET(memNum == nullptr, HCCL_ERROR("[GetIndOpRemoteMem] memNum is nullptr"), HCCL_E_PARA);
    1140              : 
    1141            0 :     *remoteMem = nullptr;
    1142            0 :     *memNum = 0;
    1143              : 
    1144            0 :     std::lock_guard<std::mutex> lock(remoteMemsMutex_);
    1145              : 
    1146            0 :     if (!remoteMemsPtr_) {
    1147            0 :         uint32_t totalCount = remoteUserDeviceMemMsg_.size() + remoteUserHostMemMsg_.size();
    1148            0 :         if (totalCount == 0) {
    1149            0 :             HCCL_INFO("[GetIndOpRemoteMem] No remote memory regions available");
    1150            0 :             return HCCL_SUCCESS;
    1151              :         }
    1152            0 :         remoteMemsPtr_ = std::make_unique<HcclMem[]>(totalCount);
    1153            0 :         CHK_PTR_NULL(remoteMemsPtr_);
    1154            0 :         uint32_t index = 0;
    1155            0 :         for (const auto& msg : remoteUserDeviceMemMsg_) {
    1156            0 :             remoteMemsPtr_[index].type = HcclMemType::HCCL_MEM_TYPE_DEVICE;
    1157            0 :             remoteMemsPtr_[index].addr = msg.addr;
    1158            0 :             remoteMemsPtr_[index].size = msg.len;
    1159            0 :             index++;
    1160              :         }
    1161            0 :         for (const auto& msg : remoteUserHostMemMsg_) {
    1162            0 :             remoteMemsPtr_[index].type = HcclMemType::HCCL_MEM_TYPE_HOST;
    1163            0 :             remoteMemsPtr_[index].addr = msg.addr;
    1164            0 :             remoteMemsPtr_[index].size = msg.len;
    1165            0 :             index++;
    1166              :         }
    1167            0 :         remoteMemsNum_ = totalCount;
    1168              :     }
    1169              : 
    1170            0 :     *memNum = remoteMemsNum_;
    1171            0 :     *remoteMem = remoteMemsPtr_.get();
    1172              : 
    1173            0 :     return HCCL_SUCCESS;
    1174            0 : }
    1175              : 
    1176            0 : HcclResult TransportIbverbs::GetRemoteMem(UserMemType memType, void **remotePtr)
    1177              : {
    1178            0 :     switch (memType) {
    1179            0 :         case UserMemType::INPUT_MEM:
    1180              :         case UserMemType::OUTPUT_MEM:
    1181            0 :             *remotePtr = remoteMemMsg_[static_cast<u32>(memType)].addr;
    1182            0 :             break;
    1183              : 
    1184            0 :         default:
    1185            0 :             HCCL_ERROR("[Get][RemoteMem]not support dst_mem_type=%d", memType);
    1186            0 :             return HCCL_E_NOT_SUPPORT;
    1187              :     }
    1188            0 :     return HCCL_SUCCESS;
    1189              : }
    1190              : 
    1191            0 : HcclResult TransportIbverbs::GetRemoteMemSize(UserMemType memType, u64 &size)
    1192              : {
    1193            0 :     switch (memType) {
    1194            0 :         case UserMemType::INPUT_MEM:
    1195              :         case UserMemType::OUTPUT_MEM:
    1196            0 :             size = remoteMemMsg_[static_cast<u32>(memType)].len;
    1197            0 :             break;
    1198              : 
    1199            0 :         default:
    1200            0 :             HCCL_ERROR("[Get][RemoteMem]not support dst_mem_type=%d", memType);
    1201            0 :             return HCCL_E_NOT_SUPPORT;
    1202              :     }
    1203            0 :     return HCCL_SUCCESS;
    1204              : }
    1205              : 
    1206            0 : HcclResult TransportIbverbs::TxSendDataAndNotifyWithSingleQP(
    1207              :     std::vector<WqeInfo> &wqeInfoVec, Stream &stream, bool useOneDoorbell)
    1208              : {
    1209            0 :     if (IsSupportRdmaNotify() && wqeInfoVec.size() > 0) {
    1210              :         // 支持RDMA NOTIFY时, 修改wqeInfoVec中最后一个wqe, 使其附带Notify信息
    1211            0 :         u32 offset = static_cast<u32>(remoteDataNotifyMsg_.offset);
    1212            0 :         if (wqeInfoVec.back().wqeData.op == RA_WR_RDMA_REDUCE_WRITE) {
    1213            0 :             wqeInfoVec.back().wqeData.op = RA_WR_RDMA_REDUCE_WRITE_WITH_NOTIFY;
    1214              :         } else {
    1215            0 :             wqeInfoVec.back().wqeData.op = RA_WR_RDMA_WRITE_WITH_NOTIFY;
    1216              :         }
    1217            0 :         wqeInfoVec.back().wqeData.aux.notifyOffset = offset;
    1218              :     } else {
    1219              :         // 发送data notify同步信息
    1220            0 :         struct WrAuxInfo aux = {0};
    1221            0 :         void *remoteNotifyaddr = remoteDataNotifyMsg_.addr;
    1222            0 :         CHK_RET(AddWqeList(remoteNotifyaddr, notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_,
    1223              :             WqeType::WQE_TYPE_DATA_NOTIFY, aux, wqeInfoVec));
    1224              :     }
    1225              : 
    1226            0 :     if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE) {
    1227            0 :         CHK_RET(RdmaSendAsync(wqeInfoVec, stream, useOneDoorbell));
    1228              :     } else {
    1229            0 :         CHK_RET(RdmaSendAsyncHostNIC(wqeInfoVec, stream));
    1230              :     }
    1231            0 :     return HCCL_SUCCESS;
    1232              : }
    1233              : 
    1234            0 : u32 TransportIbverbs::GetActualQpNum(u32 maxLength)
    1235              : {
    1236            0 :     u32 actualMultiQpNum = 1;
    1237            0 :     const u32 KByteToByte = 1024;  // 1024 多QP阈值单位是KB
    1238            0 :     if (maxLength / qpsPerConnection_ >= GetExternalInputMultiQpThreshold() * KByteToByte) {
    1239            0 :         actualMultiQpNum = qpsPerConnection_;
    1240              :     } else {
    1241            0 :         u32 quotient = maxLength / (GetExternalInputMultiQpThreshold() * KByteToByte);
    1242            0 :         u32 remainder =  maxLength % (GetExternalInputMultiQpThreshold() * KByteToByte);
    1243            0 :         actualMultiQpNum = quotient + (remainder != 0 ? 1 : 0);
    1244              :     }
    1245              : 
    1246            0 :     return actualMultiQpNum;
    1247              : }
    1248              : 
    1249            0 : HcclResult TransportIbverbs::TxSendDataAndNotify(std::vector<WqeInfo> &wqeInfoVec, Stream &stream, bool useOneDoorbell)
    1250              : {
    1251            0 :     u32 maxLength = 0;
    1252            0 :     for (u32 i = 0; i < wqeInfoVec.size(); i++) {
    1253            0 :         if (wqeInfoVec[i].wqeData.memList.len > maxLength) {
    1254            0 :             maxLength = wqeInfoVec[i].wqeData.memList.len;
    1255              :         }
    1256              :     }
    1257              :     
    1258            0 :     u32 actualMultiQpNum = GetActualQpNum(maxLength);
    1259              : 
    1260            0 :     HCCL_DEBUG("[TransportIbverbs][TxSendDataAndNotify] UseMultiQp[%d] MultiQpNum[%u] actualMultiQpNum[%u] maxLength[%u]",
    1261              :         UseMultiQp(), qpsPerConnection_, actualMultiQpNum, maxLength);
    1262            0 :     if (UseMultiQp() && actualMultiQpNum != 1 && actualMultiQpNum <= qpsPerConnection_ && maxLength != 0) {
    1263            0 :         CHK_RET(TxSendDataAndNotifyWithMultiQP(wqeInfoVec, actualMultiQpNum, stream, useOneDoorbell));
    1264              :     } else {
    1265            0 :         CHK_RET(TxSendDataAndNotifyWithSingleQP(wqeInfoVec, stream, useOneDoorbell));
    1266              :     }
    1267            0 :     return HCCL_SUCCESS;
    1268              : }
    1269              : 
    1270            0 : std::vector<u32> TransportIbverbs::RdmaLengthSplit(u32 length, u32 splitNum)
    1271              : {
    1272              :     // step 1, 先计算有多少个128 Byte
    1273            0 :     u32 alignNum = length / RDMA_ADDR_ALIGNMENT;
    1274            0 :     u32 tailBytes = length % RDMA_ADDR_ALIGNMENT;  // 尾块简单处理,放在最后一个切分出来的块后面
    1275              :     // step 2, 将这128 Byte再分成 splitNum 分,每一份有多少个 128Byte
    1276            0 :     u32 alignNumPerSplit = alignNum / splitNum;
    1277            0 :     u32 tailAlignNum = alignNum % splitNum;  // 尾块简单处理,放在最后一个切分出来的块后面
    1278            0 :     std::vector<u32> vctSplittedLength(splitNum, 0);
    1279            0 :     for (u32 i = 0; i < splitNum; i++) {
    1280            0 :         u32 lengthTmp = alignNumPerSplit * RDMA_ADDR_ALIGNMENT;
    1281            0 :         vctSplittedLength[i] = lengthTmp;
    1282              :     }
    1283            0 :     vctSplittedLength[splitNum-1] += tailAlignNum * RDMA_ADDR_ALIGNMENT + tailBytes;
    1284            0 :     return vctSplittedLength;
    1285              : }
    1286              : 
    1287            0 : HcclResult TransportIbverbs::TxSendDataAndNotifyWithMultiQP(std::vector<WqeInfo>& wqeInfoVec, u32 actualMultiQpNum,
    1288              :     Stream &stream, bool useOneDoorbell)
    1289              : {
    1290              :     // vector<WqeInfo> 是一个vector的原因是 单个wqe只能发2GB数据,如果超过2GB,就拆分到多个WqeInfo中了
    1291              :     // 多QP下,对每个WqeInfo都进行多QP切分,然后在收发每一个QP的数据
    1292            0 :     std::vector<std::vector<WqeInfo>> multiQpWqeInfoVct(actualMultiQpNum, wqeInfoVec);
    1293            0 :     for (u32 i = 0; i < wqeInfoVec.size(); i++) {
    1294            0 :         WqeInfo tmpWqeInfo = wqeInfoVec[i];
    1295            0 :         u32 curLen = tmpWqeInfo.wqeData.memList.len;
    1296            0 :         std::vector<u32> splittedLen = RdmaLengthSplit(curLen, actualMultiQpNum);
    1297            0 :         uint64_t curSrcAddr = tmpWqeInfo.wqeData.memList.addr;
    1298            0 :         uint64_t curDstAddr = tmpWqeInfo.wqeData.dstAddr;
    1299            0 :         for (u32 qpIndex = 0; qpIndex < actualMultiQpNum; qpIndex++) {
    1300            0 :             multiQpWqeInfoVct[qpIndex][i].wqeData.memList.len = splittedLen[qpIndex];
    1301            0 :             multiQpWqeInfoVct[qpIndex][i].wqeData.memList.addr = curSrcAddr;
    1302            0 :             multiQpWqeInfoVct[qpIndex][i].wqeData.dstAddr = curDstAddr;
    1303            0 :             curSrcAddr += splittedLen[qpIndex];
    1304            0 :             curDstAddr += splittedLen[qpIndex];
    1305              :         }
    1306            0 :     }
    1307              :     // 给每个QP最后增加一个属于该QP的DataNotify
    1308            0 :     for (u32 qpIndex = 0; qpIndex < actualMultiQpNum; qpIndex++) {
    1309            0 :         struct WrAuxInfo aux = {0};
    1310            0 :         void *remoteNotifyaddr = multiQpDataNotifyRemoteMemMsg_[qpIndex].addr;
    1311            0 :         CHK_RET(AddWqeList(remoteNotifyaddr, notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_,
    1312              :             WqeType::WQE_TYPE_DATA_NOTIFY, aux, multiQpWqeInfoVct[qpIndex]));
    1313              :     }
    1314              :     // useOneDoorbell 配置成true。最后一个payload去按doorbell
    1315            0 :     for (u32 qpIndex = 0; qpIndex < actualMultiQpNum; qpIndex++) {
    1316            0 :         CHK_RET(RdmaSendAsync(multiQpWqeInfoVct[qpIndex], stream, true, qpIndex)); // 多QP使用同一个stream异步doorbell触发
    1317              :     }
    1318            0 :     return HCCL_SUCCESS;
    1319            0 : }
    1320              : 
    1321            0 : HcclResult TransportIbverbs::TxAsync(std::vector<TxMemoryInfo>& txMems, Stream &stream)
    1322              : {
    1323            0 :     std::vector<WqeInfo> wqeInfoVec;
    1324            0 :     wqeInfoVec.reserve(WQE_RESERVE_LENGTH);
    1325            0 :     struct WrAuxInfo aux = {0};
    1326              : 
    1327            0 :     for (auto& mem : txMems) {
    1328            0 :         HCCL_DEBUG("TX src[%p] len[%llu] dstOffset[%llu]", mem.src, mem.len, mem.dstOffset);
    1329            0 :         CHK_PTR_NULL(mem.src);
    1330            0 :         CHK_RET(TxPayLoad(mem.dstMemType, mem.dstOffset, mem.src, mem.len, WqeType::WQE_TYPE_DATA, aux, wqeInfoVec));
    1331              :     }
    1332              : 
    1333            0 :     CHK_RET(TxSendDataAndNotify(wqeInfoVec, stream, GetUseOneDoorbellValue()));
    1334            0 :     return HCCL_SUCCESS;
    1335            0 : }
    1336              : 
    1337            1 : HcclResult TransportIbverbs::TxWqeList(std::vector<WqeInfo> &wqeInfoVec, Stream &stream,
    1338              :     std::vector<struct SendWrRsp> &opRspVec, u32 multiQpIndex)
    1339              : {
    1340              :     (void)stream;
    1341            1 :     if (!IsTemplateMode()) {
    1342            0 :         currentQP_ = 0;
    1343              :     } else {
    1344            2 :         if (sqeCounter_ < (HCCP_SQ_TEMPLATE_CAPACITY + 1) &&
    1345            1 :             (sqeCounter_ + wqeInfoVec.size()) >= (HCCP_SQ_TEMPLATE_CAPACITY + 1)) {
    1346            0 :             currentQP_++;
    1347            0 :             sqeCounter_ = wqeInfoVec.size();
    1348              :         } else {
    1349            1 :             sqeCounter_ += wqeInfoVec.size();
    1350              :         }
    1351              :     }
    1352            1 :     CHK_PRT_RET(currentQP_ >= combineQpHandles_.size(), HCCL_ERROR("[TransportIbverbs][TxWqeList]errNo[0x%016llx] In lbv "\
    1353              :         "exp, qp idx[%u] is invalid.", HCCL_ERROR_CODE(HCCL_E_INTERNAL), currentQP_), HCCL_E_INTERNAL);
    1354              : 
    1355            0 :     HCCL_DEBUG("rdma tx send wqes: ra qp sqe counter:%u, current qp idx:%u", sqeCounter_, currentQP_);
    1356              : 
    1357            0 :     std::vector<SendWrlistDataExt> wqelisDatatVec;
    1358            0 :     for (u32 index = 0; index < wqeInfoVec.size(); index++) {
    1359              :         // 使能atomic write场景下,reduce的下一个notify的opcode要设置为atomic write
    1360              :         u32& preWrOpcode = multiQpIndex == RDMA_INVALID_QP_INDEX ?
    1361            0 :             combineQpHandles_[currentQP_].preWrOpcode : multiCombineQpHandles_[multiQpIndex].preWrOpcode;
    1362            0 :         ModifyAtomicWriteAfterReduce(preWrOpcode, wqeInfoVec[index].wqeType, wqeInfoVec[index].wqeData.op,
    1363            0 :             wqeInfoVec[index].wqeData.ext.immData);
    1364              : 
    1365            0 :         wqelisDatatVec.push_back(wqeInfoVec[index].wqeData);
    1366              :     }
    1367              : 
    1368            0 :     u32 totalWqeCount = wqelisDatatVec.size();
    1369            0 :     struct SendWrlistDataExt *wqelist = wqelisDatatVec.data();
    1370            0 :     struct SendWrRsp *opRsp = opRspVec.data();
    1371              : 
    1372              :     // HCCP会校验 zero byte messages 的内存地址是否已注册MR。对于 zero byte messages 不下发WR,将opRsp设置为特殊值。
    1373              :     // 下发rdmasend task时检查该特殊值,如果zero byte message则不下发rdmasend task。
    1374            0 :     bool batchSendWr = true;
    1375            0 :     for (u32 i = 0; i < totalWqeCount; i++) {
    1376            0 :         if (wqelisDatatVec[i].memList.len == 0) {
    1377            0 :             batchSendWr = false;
    1378            0 :             break;
    1379              :         }
    1380              :     }
    1381              :     QpHandle currentQp;
    1382            0 :     if (multiQpIndex == RDMA_INVALID_QP_INDEX) {
    1383            0 :         currentQp = combineQpHandles_[currentQP_].qpHandle;
    1384              :     } else {
    1385            0 :         currentQp = multiCombineQpHandles_[multiQpIndex].qpHandle;
    1386              :     }
    1387            0 :     if (batchSendWr) {
    1388            0 :         CHK_RET(SendWqeList(currentQp, totalWqeCount, wqelist, opRsp));
    1389              :     } else {
    1390            0 :         for (u32 i = 0; i < totalWqeCount; i++) {
    1391            0 :             if (wqelisDatatVec[i].memList.len > 0) {
    1392            0 :                 CHK_RET(SendWqeList(currentQp, 1U, &wqelist[i], &opRsp[i]));
    1393              :             } else {
    1394            0 :                 opRsp[i].wqeTmp.sqIndex = INVALID_UINT;
    1395            0 :                 opRsp[i].wqeTmp.wqeIndex = INVALID_UINT;
    1396            0 :                 opRsp[i].db.dbIndex = INVALID_UINT;
    1397            0 :                 opRsp[i].db.dbInfo = INVALID_U64;
    1398              :             }
    1399              :         }
    1400              :     }
    1401              : 
    1402            0 :     return HCCL_SUCCESS;
    1403            0 : }
    1404              : 
    1405            0 : HcclResult TransportIbverbs::SendWqeList(QpHandle qpHandle, u32 wqeNum, struct SendWrlistDataExt *wqelist,
    1406              :     struct SendWrRsp *opRsp)
    1407              : {
    1408            0 :     unsigned int completeNum = 0;
    1409            0 :     HcclResult ret = HrtRaSendWrlistExt(qpHandle, wqelist, opRsp, wqeNum, &completeNum);
    1410            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
    1411              :         HCCL_ERROR("[TransportIbverbs][TxWqeList]In ibv send wq list, HrtRaSendWrlist failed.ret[%d]", ret),
    1412              :         HCCL_E_NETWORK);
    1413            0 :     return HCCL_SUCCESS;
    1414              : }
    1415              : 
    1416            1 : HcclResult TransportIbverbs::RdmaSendAsync(std::vector<WqeInfo> &wqeInfoVec, Stream &stream,
    1417              :     bool useOneDoorbell, u32 multiQpIndex)
    1418              : {
    1419              :     HcclResult ret;
    1420              : 
    1421            1 :     std::vector<struct SendWrRsp> opRspVec(wqeInfoVec.size());
    1422            1 :     CHK_RET(TxWqeList(wqeInfoVec, stream, opRspVec, multiQpIndex));
    1423              : 
    1424            0 :     std::vector<SendWrlistDataExt> wqelistVec;
    1425            0 :     for (u32 index = 0; index < wqeInfoVec.size(); index++) {
    1426            0 :         wqelistVec.push_back(wqeInfoVec[index].wqeData);
    1427              :     }
    1428              : 
    1429            0 :     struct SendWr wr = {nullptr};
    1430            0 :     wr.bufNum = 1;
    1431            0 :     wr.op = 0;
    1432            0 :     wr.sendFlag = fence_ ? (RA_SEND_SIGNALED | RA_SEND_FENCE) : RA_SEND_SIGNALED;
    1433            0 :     fence_ = false;
    1434              : 
    1435            0 :     if (useOneDoorbell && !IsTemplateMode()) {
    1436              :         // 内存块不连续时,只敲最后一次doorbell
    1437            0 :         wr.bufList = &wqelistVec.back().memList;
    1438            0 :         wr.dstAddr = static_cast<u64>(wqelistVec.back().dstAddr);
    1439              :         // 只敲一次doorbell时,len为所有非连续内存块长度总和+notify(4Bytes)
    1440            0 :         wr.bufList[0].len = std::accumulate(wqelistVec.begin(), wqelistVec.end(), 0llu,
    1441            0 :             [](u64 acc, auto wqelist) { return acc + wqelist.memList.len; });
    1442              : 
    1443            0 :         const u32 dbIndex = static_cast<u32>(opRspVec.back().db.dbIndex);
    1444            0 :         const u64 dbInfo = static_cast<u64>(opRspVec.back().db.dbInfo);
    1445            0 :         ret = dispatcher_->RdmaSend(dbIndex, dbInfo, wr, stream, machinePara_.remoteWorldRank, isCapture_);
    1446            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
    1447              :             HCCL_ERROR("[TransportIbverbs][RdmaSendAsync][useOneDoorbell]errNo[0x%016llx] In lbv exp op base mode, "\
    1448              :             "rdma send failed. dbIndex[%u] dbInfo[%llu]", HCCL_ERROR_CODE(ret), dbIndex, dbInfo), ret);
    1449            0 :         HCCL_INFO("[TransportIbverbs][RdmaSendAsync][useOneDoorbell] db_index[%u], db_info[%llu]", dbIndex, dbInfo);
    1450            0 :         return HCCL_SUCCESS;
    1451              :     }
    1452              : 
    1453            0 :     for (u32 i = 0; i < wqeInfoVec.size(); i++) {
    1454            0 :         wr.bufList = &wqelistVec[i].memList;
    1455            0 :         wr.dstAddr = static_cast<u64>(wqelistVec[i].dstAddr);
    1456              : 
    1457            0 :         if (!IsTemplateMode()) {
    1458            0 :             u32 dbIndex = static_cast<u32>(opRspVec[i].db.dbIndex);
    1459            0 :             u64 dbInfo = static_cast<u64>(opRspVec[i].db.dbInfo);
    1460              : 
    1461              :             // op base 模式下的发送接口
    1462            0 :             if (wqeInfoVec[i].wqeType == static_cast<u64>(WqeType::WQE_TYPE_DATA)) {
    1463            0 :                 ret = dispatcher_->RdmaSend(dbIndex, dbInfo, wr, stream,
    1464            0 :                     machinePara_.remoteWorldRank, isCapture_);
    1465              :             } else {
    1466            0 :                 ret = dispatcher_->RdmaSend(dbIndex, dbInfo, wr, stream,
    1467            0 :                     machinePara_.remoteWorldRank, wqeInfoVec[i].wqeDataOffset, isCapture_);
    1468              :             }
    1469            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
    1470              :                 HCCL_ERROR("[TransportIbverbs][RdmaSendAsync]errNo[0x%016llx] In lbv exp op base mode, "\
    1471              :                 "rdma send failed. dbIndex[%u] dbInfo[%llu] wqe type[%llu] offset[%llu]", HCCL_ERROR_CODE(ret), dbIndex,
    1472              :                 dbInfo, wqeInfoVec[i].wqeType, wqeInfoVec[i].wqeDataOffset), ret);
    1473              :         } else { // offline mode
    1474              :             // 下沉模式
    1475            0 :             if (wqeInfoVec[i].wqeType == static_cast<u64>(WqeType::WQE_TYPE_DATA)) {
    1476            0 :                 ret = dispatcher_->RdmaSend(opRspVec[i].wqeTmp.sqIndex, opRspVec[i].wqeTmp.wqeIndex,
    1477              :                     wr, stream, machinePara_.remoteWorldRank);
    1478              :             } else {
    1479            0 :                 ret = dispatcher_->RdmaSend(opRspVec[i].wqeTmp.sqIndex, opRspVec[i].wqeTmp.wqeIndex,
    1480            0 :                     wr, stream, machinePara_.remoteWorldRank, wqeInfoVec[i].wqeDataOffset);
    1481              :             }
    1482            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
    1483              :                 HCCL_ERROR("[TransportIbverbs][RdmaSendAsync]errNo[0x%016llx] In lbv exp offline mode, "\
    1484              :                 "rdma send failed. sq_index[%u] wqe_index[%u], offset[%llu]", HCCL_ERROR_CODE(ret),
    1485              :                 opRspVec[i].wqeTmp.sqIndex, opRspVec[i].wqeTmp.wqeIndex, wqeInfoVec[i].wqeDataOffset), ret);
    1486              :         }
    1487              :     }
    1488            0 :     return HCCL_SUCCESS;
    1489            1 : }
    1490            0 : HcclResult TransportIbverbs::RdmaSendAsyncHostNIC(std::vector<WqeInfo> &wqeInfoVec, Stream &stream)
    1491              : {
    1492              :     HcclResult ret;
    1493              : 
    1494            0 :     std::vector<SendWrlistDataExt> wqelistVec;
    1495            0 :     for (u32 index = 0; index < wqeInfoVec.size(); index++) {
    1496            0 :         wqelistVec.push_back(wqeInfoVec[index].wqeData);
    1497              :     }
    1498            0 :     struct SendWrRsp opRsp = {0};
    1499            0 :     struct SendWrlistDataExt wr = {0};
    1500            0 :     for (u32 i = 0; i < wqeInfoVec.size(); i++) {
    1501            0 :         wr.memList.addr = wqelistVec[i].memList.addr;
    1502            0 :         wr.memList.len = wqelistVec[i].memList.len;
    1503            0 :         wr.dstAddr = static_cast<u64>(wqelistVec[i].dstAddr);
    1504            0 :         wr.op = 0;
    1505            0 :         wr.sendFlags = fence_ ? (RA_SEND_SIGNALED | RA_SEND_FENCE) : RA_SEND_SIGNALED;
    1506            0 :         fence_ = false;
    1507              : 
    1508            0 :         if (wqeInfoVec[i].wqeType == static_cast<u64>(WqeType::WQE_TYPE_DATA)) {
    1509            0 :                 ret = dispatcher_->HostNicRdmaSend(combineQpHandles_[0].qpHandle, wr,
    1510              :                     opRsp, stream, machinePara_.remoteWorldRank);
    1511              :             } else {
    1512            0 :                 ret = dispatcher_->HostNicRdmaSend(combineQpHandles_[0].qpHandle, wr,
    1513              :                     opRsp, stream, machinePara_.remoteWorldRank,
    1514            0 :                     wqeInfoVec[i].wqeDataOffset);
    1515              :             }
    1516            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
    1517              :             HCCL_ERROR("[TransportIbverbs][RdmaSendAsyncHostNIC]errNo[0x%016llx] In lbv exp offline " \
    1518              :             "mode, rdma send failed. sq_index[%u] wqe_index[%u], offset[%llu]", HCCL_ERROR_CODE(ret),
    1519              :             opRsp.wqeTmp.sqIndex, opRsp.wqeTmp.wqeIndex, wqeInfoVec[i].wqeDataOffset), ret);
    1520              :     }
    1521            0 :     return HCCL_SUCCESS;
    1522            0 : }
    1523            0 : HcclResult TransportIbverbs::RdmaSendAsync(struct SendWr &wr, Stream &stream, WqeType wqeType, u64 notifyOffset,
    1524              :     u32 notifyId)
    1525              : {
    1526              :     HcclResult ret;
    1527            0 :     struct SendWrRsp opRsp = {0};
    1528            0 :     if (!IsTemplateMode()) {
    1529            0 :         currentQP_ = 0;
    1530              :     } else {
    1531            0 :         if (sqeCounter_ == HCCP_SQ_TEMPLATE_CAPACITY) {
    1532            0 :             currentQP_++;
    1533            0 :             sqeCounter_ = 1;
    1534              :         } else {
    1535            0 :             sqeCounter_++;
    1536              :         }
    1537              :     }
    1538            0 :     CHK_PRT_RET(currentQP_ >= combineQpHandles_.size(), HCCL_ERROR("[TransportIbverbs][RdmaSendAsync]errNo[0x%016llx] In "\
    1539              :         "lbv exp, qp idx[%u] is invalid.", HCCL_ERROR_CODE(HCCL_E_INTERNAL), currentQP_), HCCL_E_INTERNAL);
    1540            0 :     HCCL_DEBUG("rdma send async: ra qp sqe counter:%u, current qp idx:%u.",
    1541              :         sqeCounter_, currentQP_);
    1542              : 
    1543            0 :     CHK_RET(HrtRaSendWr(combineQpHandles_[currentQP_].qpHandle, &wr, &opRsp));
    1544              : 
    1545            0 :     if (!IsTemplateMode()) {
    1546            0 :         u32 dbIndex = static_cast<u32>(opRsp.db.dbIndex);
    1547            0 :         u64 dbInfo = static_cast<u64>(opRsp.db.dbInfo);
    1548            0 :         if (wqeType == WqeType::WQE_TYPE_DATA) {
    1549            0 :             ret = dispatcher_->RdmaSend(dbIndex, dbInfo, wr, stream,
    1550            0 :                 machinePara_.remoteWorldRank, isCapture_);
    1551            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
    1552              :                 HCCL_ERROR("[TransportIbverbs][RdmaSendAsync]errNo[0x%016llx] In lbv exp op base mode, "\
    1553              :                 "rdma send failed. dbIndex[%u] dbInfo[%llu]", HCCL_ERROR_CODE(ret), dbIndex, dbInfo), ret);
    1554              :         } else {
    1555            0 :             ret = dispatcher_->RdmaSend(dbIndex, dbInfo, wr, stream,
    1556            0 :                 machinePara_.remoteWorldRank, notifyOffset, isCapture_);
    1557            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
    1558              :                 HCCL_ERROR("[TransportIbverbs][RdmaSendAsync]errNo[0x%016llx] In lbv exp op base mode, "\
    1559              :                 "rdma send failed. dbIndex[%u] dbInfo[%llu], offset[%llu]", HCCL_ERROR_CODE(ret), dbIndex, dbInfo,
    1560              :                 notifyOffset), ret);
    1561              :         }
    1562              :     } else { // offline mode
    1563            0 :         if (wqeType == WqeType::WQE_TYPE_DATA) {
    1564            0 :             ret = dispatcher_->RdmaSend(opRsp.wqeTmp.sqIndex, opRsp.wqeTmp.wqeIndex,
    1565              :                 wr, stream, machinePara_.remoteWorldRank);
    1566            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
    1567              :                 HCCL_ERROR("[TransportIbverbs][RdmaSendAsync]errNo[0x%016llx] In lbv exp offline mode, "\
    1568              :                 "rdma send failed. sq_index[%u] wqe_index[%u]", HCCL_ERROR_CODE(ret), opRsp.wqeTmp.sqIndex,
    1569              :                 opRsp.wqeTmp.wqeIndex), ret);
    1570              :         } else {
    1571            0 :             ret = dispatcher_->RdmaSend(opRsp.wqeTmp.sqIndex, opRsp.wqeTmp.wqeIndex,
    1572              :                 wr, stream, machinePara_.remoteWorldRank, notifyOffset);
    1573            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
    1574              :                 HCCL_ERROR("[TransportIbverbs][RdmaSendAsync]errNo[0x%016llx] In lbv exp offline mode, "\
    1575              :                 "rdma send failed. sq_index[%u] wqe_index[%u], offset[%llu]", HCCL_ERROR_CODE(ret),
    1576              :                 opRsp.wqeTmp.sqIndex, opRsp.wqeTmp.wqeIndex, notifyOffset), ret);
    1577              :         }
    1578              :     }
    1579            0 :     return HCCL_SUCCESS;
    1580              : }
    1581            0 : HcclResult TransportIbverbs::RdmaSendAsyncHostNIC(struct SendWrlistDataExt &wr, Stream &stream, WqeType wqeType,
    1582              :     u64 notifyOffset)
    1583              : {
    1584              :     HcclResult ret;
    1585            0 :     struct SendWrRsp opRsp = {0};
    1586            0 :     if (wqeType == WqeType::WQE_TYPE_DATA) {
    1587            0 :             ret = dispatcher_->HostNicRdmaSend(combineQpHandles_[0].qpHandle, wr,
    1588              :                 opRsp, stream, machinePara_.remoteWorldRank);
    1589              :         } else {
    1590            0 :             ret = dispatcher_->HostNicRdmaSend(combineQpHandles_[0].qpHandle, wr,
    1591              :                 opRsp, stream, machinePara_.remoteWorldRank,
    1592              :                 notifyOffset);
    1593              :     }
    1594            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
    1595              :         HCCL_ERROR("[TransportIbverbs][RdmaSendAsyncHostNIC]errNo[0x%016llx] In lbv exp offline mode, "\
    1596              :         "rdma send failed. sq_index[%u] wqe_index[%u], offset[%llu]", HCCL_ERROR_CODE(ret),
    1597              :         opRsp.wqeTmp.sqIndex, opRsp.wqeTmp.wqeIndex, notifyOffset), ret);
    1598              : 
    1599            0 :     return HCCL_SUCCESS;
    1600              : }
    1601            1 : HcclResult TransportIbverbs::GetWqeDataOffsetAndNotifyId(WqeType wqeType, u64 &wqeDataOffset, u32 &notifyId)
    1602              : {
    1603            1 :     switch (wqeType) {
    1604            1 :         case WqeType::WQE_TYPE_DATA:
    1605              :         case WqeType::WQE_TYPE_DATA_WITH_NOTIFY:
    1606              :         case WqeType::WQE_TYPE_DATA_WITH_REDUCE:
    1607              :         case WqeType::WQE_TYPE_READ_DATA:
    1608            1 :             wqeDataOffset = 0;
    1609            1 :             notifyId = INVALID_UINT;
    1610            1 :             break;
    1611            0 :         case WqeType::WQE_TYPE_DATA_NOTIFY:
    1612            0 :             wqeDataOffset = remoteDataNotifyMsg_.offset;
    1613            0 :             notifyId = remoteDataNotifyMsg_.notifyId;
    1614            0 :             break;
    1615            0 :         case WqeType::WQE_TYPE_ACK_NOTIFY:
    1616            0 :             wqeDataOffset = remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].offset;
    1617            0 :             notifyId = remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].notifyId;
    1618            0 :             break;
    1619            0 :         case WqeType::WQE_TYPE_DATA_ACK_NOTIFY:
    1620            0 :             wqeDataOffset = remoteMemMsg_[static_cast<u32>(MemType::DATA_ACK_NOTIFY_MEM)].offset;
    1621            0 :             notifyId = remoteMemMsg_[static_cast<u32>(MemType::DATA_ACK_NOTIFY_MEM)].notifyId;
    1622            0 :             break;
    1623            0 :         default:
    1624            0 :             HCCL_ERROR("[Get][WqeDataOffset]error wqeType[%d]", wqeType);
    1625            0 :             return HCCL_E_INTERNAL;
    1626              :     }
    1627            1 :     return HCCL_SUCCESS;
    1628              : }
    1629              : 
    1630            0 : HcclResult TransportIbverbs::TxSendWqe(void *dstMemPtr, const void *srcMemPtr, u64 srcMemSize,
    1631              :                                        Stream &stream, WqeType wqeType)
    1632              : {
    1633            0 :     if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE && !useAtomicWrite_) {
    1634            0 :         struct SgList list = {0};
    1635            0 :         struct SendWr wr = {nullptr};
    1636              :         // 构造wr信息
    1637            0 :         list.addr = static_cast<u64>(reinterpret_cast<uintptr_t>(srcMemPtr));
    1638            0 :         list.len = srcMemSize;
    1639              : 
    1640            0 :         wr.bufList = &list;
    1641            0 :         wr.bufNum = 1; /* 此处list只有一个,设置为1 */
    1642            0 :         wr.dstAddr = static_cast<u64>(reinterpret_cast<uintptr_t>(dstMemPtr));
    1643            0 :         wr.op = 0; /* RDMA_WRITE: 0 */
    1644            0 :         wr.sendFlag = fence_ ? (RA_SEND_SIGNALED | RA_SEND_FENCE) : RA_SEND_SIGNALED;
    1645            0 :         fence_ = false;
    1646              : 
    1647              :         // 获取notify偏移地址,对于发送数据时,偏移地址为0
    1648            0 :         u32 notifyId = INVALID_UINT;
    1649            0 :         u64 wqeDataOffset = 0;
    1650            0 :         CHK_RET(GetWqeDataOffsetAndNotifyId(wqeType, wqeDataOffset, notifyId));
    1651              : 
    1652              :         // RDMA异步发送
    1653            0 :         CHK_RET(RdmaSendAsync(wr, stream, wqeType, wqeDataOffset, notifyId));
    1654            0 :     } else if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE && useAtomicWrite_) {
    1655            0 :         struct WrAuxInfo aux = {0};
    1656            0 :         std::vector<WqeInfo> wqeInfoVec;
    1657            0 :         CHK_RET(AddWqeList(dstMemPtr, srcMemPtr, srcMemSize, wqeType, aux, wqeInfoVec));
    1658            0 :         CHK_RET(RdmaSendAsync(wqeInfoVec, stream, false));
    1659            0 :         HCCL_DEBUG("TxSendWqe useAtomicWrite[%d]", useAtomicWrite_);
    1660            0 :     } else {
    1661            0 :         struct SendWrlistDataExt wr = {0};
    1662              :         // 构造wr信息
    1663            0 :         wr.memList.addr = static_cast<u64>(reinterpret_cast<uintptr_t>(srcMemPtr));
    1664            0 :         wr.memList.len = srcMemSize;
    1665              : 
    1666            0 :         wr.dstAddr = static_cast<u64>(reinterpret_cast<uintptr_t>(dstMemPtr));
    1667            0 :         wr.op = 0; /* RDMA_WRITE: 0 */
    1668            0 :         wr.sendFlags = fence_ ? (RA_SEND_SIGNALED | RA_SEND_FENCE) : RA_SEND_SIGNALED;
    1669            0 :         fence_ = false;
    1670              : 
    1671              :         // 获取notify偏移地址,对于发送数据时,偏移地址为0
    1672            0 :         u32 notifyId = INVALID_UINT;
    1673            0 :         u64 wqeDataOffset = 0;
    1674            0 :         CHK_RET(GetWqeDataOffsetAndNotifyId(wqeType, wqeDataOffset, notifyId));
    1675              : 
    1676              :         // RDMA异步发送
    1677            0 :         CHK_RET(RdmaSendAsyncHostNIC(wr, stream, wqeType, wqeDataOffset));
    1678              :     }
    1679            0 :     return HCCL_SUCCESS;
    1680              : }
    1681              : 
    1682            0 : HcclResult TransportIbverbs::TxSendNotifyWqe(MemMsg& memMsg, const void *srcMemPtr, u64 srcMemSize,
    1683              :                                        Stream &stream)
    1684              : {
    1685            0 :     if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE && !useAtomicWrite_) {
    1686            0 :         struct SgList list = {0};
    1687            0 :         struct SendWr wr = {nullptr};
    1688              :         // 构造wr信息
    1689            0 :         list.addr = static_cast<u64>(reinterpret_cast<uintptr_t>(srcMemPtr));
    1690            0 :         list.len = srcMemSize;
    1691            0 :         wr.bufList = &list;
    1692            0 :         wr.bufNum = 1; /* 此处list只有一个,设置为1 */
    1693            0 :         wr.dstAddr = static_cast<u64>(reinterpret_cast<uintptr_t>(memMsg.addr));
    1694            0 :         wr.op = 0; /* RDMA_WRITE: 0 */
    1695            0 :         wr.sendFlag = fence_ ? (RA_SEND_SIGNALED | RA_SEND_FENCE) : RA_SEND_SIGNALED;
    1696            0 :         fence_ = false;
    1697              : 
    1698              :         // RDMA异步发送
    1699            0 :         CHK_RET(RdmaSendAsync(wr, stream, WqeType::WQE_TYPE_ACK_NOTIFY, memMsg.offset, memMsg.notifyId));
    1700            0 :     } else if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE && useAtomicWrite_) {
    1701            0 :         struct WrAuxInfo aux = {0};
    1702            0 :         std::vector<WqeInfo> wqeInfoVec;
    1703            0 :         CHK_RET(AddWqeList(memMsg.addr, srcMemPtr, srcMemSize, WqeType::WQE_TYPE_ACK_NOTIFY, aux, wqeInfoVec));
    1704            0 :         CHK_RET(RdmaSendAsync(wqeInfoVec, stream, false));
    1705            0 :         HCCL_DEBUG("TxSendNotifyWqe useAtomicWrite[%d]", useAtomicWrite_);
    1706            0 :     } else {
    1707            0 :         struct SendWrlistDataExt wr = {0};
    1708              :         // 构造wr信息
    1709            0 :         wr.memList.addr = static_cast<u64>(reinterpret_cast<uintptr_t>(srcMemPtr));
    1710            0 :         wr.memList.len = srcMemSize;
    1711            0 :         wr.dstAddr = static_cast<u64>(reinterpret_cast<uintptr_t>(memMsg.addr));
    1712            0 :         wr.op = 0; /* RDMA_WRITE: 0 */
    1713            0 :         wr.sendFlags = fence_ ? (RA_SEND_SIGNALED | RA_SEND_FENCE) : RA_SEND_SIGNALED;
    1714            0 :         fence_ = false;
    1715              : 
    1716              :         // RDMA异步发送
    1717            0 :         CHK_RET(RdmaSendAsyncHostNIC(wr, stream, WqeType::WQE_TYPE_ACK_NOTIFY, memMsg.offset));
    1718              :     }
    1719            0 :     return HCCL_SUCCESS;
    1720              : }
    1721              : 
    1722            0 : HcclResult TransportIbverbs::RxAsync(UserMemType srcMemType, u64 srcOffset, void *dst, u64 len, Stream &stream)
    1723              : {
    1724            0 :     u32 actualMultiQpNum = 1;
    1725            0 :     const u32 KByteToByte = 1024;  // 1024 多QP阈值单位是KB
    1726            0 :     if (len / qpsPerConnection_ > GetExternalInputMultiQpThreshold() * KByteToByte) {
    1727            0 :         actualMultiQpNum = qpsPerConnection_;
    1728              :     } else {
    1729            0 :         u32 quotient = len / (GetExternalInputMultiQpThreshold() * KByteToByte);
    1730            0 :         u32 remainder =  len % (GetExternalInputMultiQpThreshold() * KByteToByte);
    1731            0 :         actualMultiQpNum = quotient + (remainder != 0 ? 1 : 0);
    1732              :     }
    1733              :     // 等待TS把任务处理完成
    1734            0 :     HCCL_DEBUG("[TransportIbverbs][RxAsync] UseMultiQp[%d] actualMultiQpNum[%u], RX dst[%p] len[%llu] srcOffset[%llu]", UseMultiQp(), actualMultiQpNum, dst, len, srcOffset);
    1735            0 :     if (UseMultiQp() && actualMultiQpNum != 1 && actualMultiQpNum <= qpsPerConnection_ && len != 0) {
    1736            0 :         for (u32 i = 0; i < actualMultiQpNum; i++) {
    1737            0 :             CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, multiQpDataNotify_[i], INVALID_VALUE_STAGE,
    1738              :                 NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    1739              :         }
    1740              :     } else {
    1741            0 :         CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, dataNotify_, INVALID_VALUE_STAGE,
    1742              :             NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    1743              :     }
    1744            0 :     return HCCL_SUCCESS;
    1745              : }
    1746              : 
    1747            0 : HcclResult TransportIbverbs::RxAsync(std::vector<RxMemoryInfo>& rxMems, Stream &stream)
    1748              : {
    1749            0 :     CHK_PRT_RET(rxMems.size() == 0, HCCL_ERROR("Invalid rxMem size[%u]", rxMems.size()), HCCL_E_PARA);
    1750            0 :     for (auto& mem : rxMems) {
    1751            0 :         HCCL_DEBUG("RX dst[%p] len[%llu] dstOffset[%llu]", mem.dst, mem.len, mem.srcOffset);
    1752              :     }
    1753            0 :     u32 maxLength = 0;
    1754            0 :     for (u32 i = 0; i < rxMems.size(); i++) {
    1755            0 :         if (rxMems[i].len > maxLength) {
    1756            0 :             maxLength = rxMems[i].len;
    1757              :         }
    1758              :     }
    1759              : 
    1760            0 :     CHK_RET(RxAsync(rxMems[0].srcMemType, rxMems[0].srcOffset, rxMems[0].dst, maxLength, stream));
    1761            0 :     return HCCL_SUCCESS;
    1762              : }
    1763              : 
    1764            0 : HcclResult TransportIbverbs::DataReceivedAck(Stream &stream)
    1765              : {
    1766            0 :     CHK_RET(PostFinAck(stream));
    1767            0 :     CHK_RET(WaitFinAck(stream));
    1768              : 
    1769            0 :     return HCCL_SUCCESS;
    1770              : }
    1771              : 
    1772            0 : HcclResult TransportIbverbs::TxWaitDone(Stream &stream)
    1773              : {
    1774            0 :     return HCCL_SUCCESS;
    1775              : }
    1776              : 
    1777              : /* 发送ack消息(同步模式) */
    1778            0 : HcclResult TransportIbverbs::TxAck(Stream &stream)
    1779              : {
    1780            0 :     CHK_RET(TxSendWqe(remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].addr,
    1781              :         notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_,
    1782              :         stream, WqeType::WQE_TYPE_ACK_NOTIFY));
    1783            0 :     return HCCL_SUCCESS;
    1784              : }
    1785              : 
    1786              : /* 接收ack消息(同步模式) */
    1787            0 : HcclResult TransportIbverbs::RxAck(Stream &stream)
    1788              : {
    1789            0 :     HcclResult ret = LocalIpcNotify::Wait(stream, dispatcher_, ackNotify_, INVALID_VALUE_STAGE,
    1790              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank);
    1791            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
    1792              :         HCCL_ERROR("[TransportIbverbs][RxAck]errNo[0x%016llx] In lbv exp rx ack, signal wait failed. ",
    1793              :             HCCL_ERROR_CODE(ret)), ret);
    1794              : 
    1795            0 :     return HCCL_SUCCESS;
    1796              : }
    1797              : 
    1798            0 : HcclResult TransportIbverbs::TxDataSignal(Stream &stream)
    1799              : {
    1800              :     // 发送data notify同步信息
    1801            0 :     void *remoteNotifyaddr = remoteDataNotifyMsg_.addr;
    1802            0 :     HcclResult ret = TxSendWqe(remoteNotifyaddr, notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_, stream,
    1803              :         WqeType::WQE_TYPE_DATA_NOTIFY);
    1804            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
    1805              :         HCCL_ERROR("[TransportIbverbs][TxDataSignal]errNo[0x%016llx] In ibv tx data signal, send notify "\
    1806              :         "wqe failed. dstMemPtr[%p], srcMemPtr[%p], srcMemSize[%llu Byte]", HCCL_ERROR_CODE(ret), remoteNotifyaddr,
    1807              :         notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_), ret);
    1808              :     // 每发送一个data notify wqe, count 自增
    1809            0 :     return HCCL_SUCCESS;
    1810              : }
    1811              : 
    1812            0 : HcclResult TransportIbverbs::RxDataSignal(Stream &stream)
    1813              : {
    1814              :     /* 等待send_ready_event事件 */
    1815            0 :     CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, dataNotify_, INVALID_VALUE_STAGE,
    1816              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    1817            0 :     return HCCL_SUCCESS;
    1818              : }
    1819              : 
    1820            0 : HcclResult TransportIbverbs::CreateNotifyVectorBuffer(std::vector<std::shared_ptr<LocalIpcNotify>> &notifyVector,
    1821              :     u8*& exchangeDataPtr, u64& exchangeDataBlankSize)
    1822              : {
    1823            0 :     NotifyLoadType notifyLoadType = machinePara_.isAicpuModeEn ?
    1824              :         NotifyLoadType::DEVICE_NOTIFY : NotifyLoadType::HOST_NOTIFY;
    1825            0 :     for (u32 i = 0; i < notifyNum_; i++) {
    1826            0 :         std::shared_ptr<LocalIpcNotify> oneNotify;
    1827            0 :         CHK_RET(CreateNotifyBuffer(oneNotify, MemType::MUILT_NOTIFY_MEM, exchangeDataPtr,
    1828              :             exchangeDataBlankSize, notifyLoadType));
    1829            0 :         notifyVector.push_back(std::move(oneNotify));
    1830            0 :     }
    1831            0 :     return HCCL_SUCCESS;
    1832              : }
    1833              : 
    1834            0 : HcclResult TransportIbverbs::CreateNotifyBuffer(std::shared_ptr<LocalIpcNotify> &localNotify, MemType notifyType,
    1835              :     u8*& exchangeDataPtr, u64& exchangeDataBlankSize, NotifyLoadType notifyLoadType)
    1836              : {
    1837            0 :     u64 offset = 0;
    1838            0 :     u64 notifyBaseVa = 0;  // notify寄存器虚拟地址
    1839            0 :     u64 notifyTotalSize = 0;
    1840            0 :     u32 notifyKey = 0;
    1841              : 
    1842            0 :     HcclRtNotify notify = nullptr;
    1843              : 
    1844              :     /* 获取notify寄存器虚拟基地址、大小, 物理地址回传值为空 */
    1845            0 :     struct MrInfoT mrInfo = {nullptr};
    1846            0 :     if (machinePara_.isAicpuModeEn || (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE &&
    1847            0 :         machinePara_.deviceType != localDeviceType) || isHybridMode_) {
    1848            0 :         CHK_RET(HrtRaGetNotifyMrInfo(machinePara_.localDeviceId, nicRdmaHandle_, &mrInfo));
    1849            0 :         notifyBaseVa = reinterpret_cast<u64>(mrInfo.addr);
    1850            0 :         notifyTotalSize = mrInfo.size;
    1851            0 :         notifyKey = mrInfo.lkey;
    1852            0 :     } else {
    1853            0 :         u64 notifyBaseVaTmp = 0;
    1854            0 :         notifyBaseVaTmp = notifyBaseVa;
    1855            0 :         CHK_RET(HrtRaGetNotifyBaseAddr(nicRdmaHandle_, &notifyBaseVa, &notifyTotalSize,
    1856              :             [this]() -> bool { return this->GetStopFlag(); }));
    1857            0 :         CHK_PRT_RET(((notifyBaseVaTmp != 0) && (notifyBaseVaTmp != notifyBaseVa)),
    1858              :             HCCL_ERROR("[Create][NotifyBuffer]In lbv exp init, get base addr failed. notify base va has changed."),
    1859              :             HCCL_E_INTERNAL);
    1860              :     }
    1861              : 
    1862              :     /* 申请Notify Group ID */
    1863            0 :     RemoteRankInfo info(machinePara_.localDeviceId, machinePara_.remoteUserrank);
    1864            0 :     CHK_RET(SalGetBareTgid(&info.remotePid)); // 当前进程id
    1865              : 
    1866              :     // atomic write使能场景下,要求写入wr的notify地址是8byte对齐的
    1867            0 :     u32 offsetAlignSize = INVALID_UINT;
    1868            0 :     if (machinePara_.enableAtomicWrite) {
    1869              :         // 映射的MR基地址必定是8字节对齐的
    1870            0 :         CHK_PRT_RET(notifyBaseVa % NOTIFY_VA_ALIGN_EIGHT != 0,
    1871              :             HCCL_ERROR("%s notifyBaseVa[0x%llx] not %u aligned", __func__, notifyBaseVa, NOTIFY_VA_ALIGN_EIGHT),
    1872              :             HCCL_E_INTERNAL);
    1873            0 :         offsetAlignSize = NOTIFY_VA_ALIGN_EIGHT;
    1874              :     }
    1875            0 :     CHK_RET(notifyPool_->Alloc(machinePara_.tag, info, localNotify, notifyLoadType, offsetAlignSize));
    1876              :     // 设置remote id
    1877            0 :     s64 recvId = 0xFFFFFFFF00000000 | (static_cast<s64>(info.remotePid) & 0xFFFFFFFF);
    1878            0 :     CHK_RET(localNotify->Grant(recvId));
    1879              : 
    1880              :     /* 获取notify虚拟地址 */
    1881            0 :     CHK_RET(localNotify->GetNotifyOffset(offset));
    1882              : 
    1883              :     // notify寄存器的虚拟地址与物理地址偏移相同,所以虚拟地址为虚拟基地址加偏移
    1884            0 :     u64 notifyVa = notifyBaseVa + offset;
    1885            0 :     CHK_PRT_RET(machinePara_.enableAtomicWrite && (notifyVa % NOTIFY_VA_ALIGN_EIGHT != 0),
    1886              :         HCCL_ERROR("%s notifyVa[0x%llx] not %u aligned, notifyBaseVa[0x%llx], offset[0x%llx], enableAtomicWrite[%d]",
    1887              :         __func__, notifyVa, NOTIFY_VA_ALIGN_EIGHT, notifyBaseVa, offset, machinePara_.enableAtomicWrite),
    1888              :         HCCL_E_INTERNAL);
    1889              : 
    1890            0 :     HCCL_INFO("%s notifyBaseVa=0x%llx, notifyTotalSize=0x%x, offset=0x%llx, notifyVa=0x%llx machineType=%d, "\
    1891              :         "notify=%p, notifyType=%d, notifyId=%u, offsetAlignSize[%u]", __func__, notifyBaseVa, notifyTotalSize, offset,
    1892              :         notifyVa, machinePara_.machineType, notify, notifyType, localNotify->notifyId_, offsetAlignSize);
    1893              : 
    1894            0 :     if (notifyType != MULTI_QP_DATA_NOTIFY_MEM) {
    1895              :         /* notify地址注册为mr, 在roce驱动中注册 */
    1896            0 :         memMsg_[static_cast<u32>(notifyType)].mrRegFlag = 0; // mem注册给网卡标志位
    1897              :         // 本端notify地址交换给对端
    1898            0 :         memMsg_[static_cast<u32>(notifyType)].addr = reinterpret_cast<void *>(static_cast<uintptr_t>(notifyVa));
    1899            0 :         memMsg_[static_cast<u32>(notifyType)].len = notifySize_;
    1900            0 :         memMsg_[static_cast<u32>(notifyType)].memType = notifyType;
    1901            0 :         memMsg_[static_cast<u32>(notifyType)].offset = offset;
    1902            0 :         memMsg_[static_cast<u32>(notifyType)].lkey = mrInfo.lkey;
    1903            0 :         memMsg_[static_cast<u32>(notifyType)].lkey = notifyKey;
    1904            0 :         memMsg_[static_cast<u32>(notifyType)].notifyId = localNotify->notifyId_;
    1905              : 
    1906              :         /* 拼接要发送的数据 */
    1907            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(exchangeDataPtr, exchangeDataBlankSize,
    1908              :             reinterpret_cast<void*>(&memMsg_[static_cast<u32>(notifyType)]), sizeof(MemMsg)));
    1909              :     } else {
    1910            0 :         MemMsg memMsg;
    1911            0 :         memMsg.mrRegFlag = 0;
    1912            0 :         memMsg.addr = reinterpret_cast<void *>(static_cast<uintptr_t>(notifyVa));
    1913            0 :         memMsg.len = notifySize_;
    1914            0 :         memMsg.memType = notifyType;
    1915            0 :         memMsg.offset = offset;
    1916            0 :         memMsg.notifyId = localNotify->notifyId_;
    1917            0 :         multiQpDataNotifyMemMsg_.push_back(std::move(memMsg));
    1918            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(exchangeDataPtr, exchangeDataBlankSize,
    1919              :             reinterpret_cast<void*>(&memMsg), sizeof(MemMsg)));
    1920              :     }
    1921              : 
    1922            0 :     exchangeDataPtr += sizeof(MemMsg);
    1923            0 :     exchangeDataBlankSize -= sizeof(MemMsg);
    1924              : 
    1925            0 :     return HCCL_SUCCESS;
    1926              : }
    1927              : 
    1928            1 : HcclResult TransportIbverbs::RegUserMem(MemType memType, u8*& exchangeDataPtr, u64& exchangeDataBlankSize)
    1929              : {
    1930            1 :     void *memPtr = nullptr;
    1931              :     u64 memSize;
    1932            1 :     switch (memType) {
    1933            1 :         case MemType::USER_INPUT_MEM: {
    1934            1 :             memPtr = machinePara_.inputMem.ptr();
    1935            1 :             memSize = machinePara_.inputMem.size();
    1936            1 :             break;
    1937              :         }
    1938              : 
    1939            0 :         case MemType::USER_OUTPUT_MEM: {
    1940            0 :             memPtr = machinePara_.outputMem.ptr();
    1941            0 :             memSize = machinePara_.outputMem.size();
    1942            0 :             break;
    1943              :         }
    1944              : 
    1945            0 :         default: {
    1946            0 :             HCCL_ERROR("[Reg][UserMem]not support dst_mem_type=%d", memType);
    1947            0 :             return HCCL_E_NOT_SUPPORT;
    1948              :         }
    1949              :     }
    1950            1 :     struct MrInfoT mrInfo = {nullptr};
    1951            1 :     mrInfo.addr = memPtr;
    1952            1 :     mrInfo.size = memSize;
    1953            1 :     mrInfo.access = access_;
    1954            1 :     if (mrInfo.size != 0) {
    1955            1 :         for (u32 i = 0; i < combineQpHandles_.size(); i++) {
    1956            0 :             CHK_RET(HrtRaMrReg(combineQpHandles_[i].qpHandle, &mrInfo));
    1957              :         }
    1958              : 
    1959            1 :         if (UseMultiQp()) {
    1960            0 :             for (u32 i = 0; i < qpsPerConnection_; i++) {
    1961            0 :                 CHK_RET(HrtRaMrReg(multiCombineQpHandles_[i].qpHandle, &mrInfo));
    1962              :             }
    1963              :         }
    1964            1 :         memMsg_[static_cast<u32>(memType)].mrRegFlag = REG_VALID;
    1965              :     }
    1966              : 
    1967            1 :     memMsg_[static_cast<u32>(memType)].addr = memPtr;
    1968            1 :     memMsg_[static_cast<u32>(memType)].len = memSize;
    1969            1 :     memMsg_[static_cast<u32>(memType)].memType = memType;
    1970            1 :     memMsg_[static_cast<u32>(memType)].lkey = mrInfo.lkey;
    1971              : 
    1972            1 :     CHK_SAFETY_FUNC_RET(memcpy_s(exchangeDataPtr, exchangeDataBlankSize,
    1973              :         reinterpret_cast<void*>(&memMsg_[static_cast<u32>(memType)]), sizeof(MemMsg)));
    1974              : 
    1975            1 :     exchangeDataPtr += sizeof(MemMsg);
    1976            1 :     exchangeDataBlankSize -= sizeof(MemMsg);
    1977              : 
    1978            1 :     HCCL_DEBUG("memType=%d mem_ptr=%p mem_size=%llu Byte, key = %u", memType, memPtr, memSize, mrInfo.lkey);
    1979              : 
    1980            1 :     return HCCL_SUCCESS;
    1981              : }
    1982              : 
    1983            0 : HcclResult TransportIbverbs::RegCustomUserMemWithMsg(void *addr, u64 size, 
    1984              :     MemMsg &memMsg, u8 *&exchangeDataPtr, u64 &exchangeDataBlankSize)
    1985              : {
    1986            0 :     struct MrInfoT mrInfo = {nullptr};
    1987            0 :     mrInfo.addr = addr;
    1988            0 :     mrInfo.size = size;
    1989            0 :     mrInfo.access = access_;
    1990            0 :     for (u32 i = 0; i < combineQpHandles_.size(); i++) {
    1991            0 :         CHK_RET(HrtRaMrReg(combineQpHandles_[i].qpHandle, &mrInfo));
    1992              :     }
    1993              : 
    1994            0 :     if (UseMultiQp()) {
    1995            0 :         for (u32 i = 0; i < qpsPerConnection_; i++) {
    1996            0 :             CHK_RET(HrtRaMrReg(multiCombineQpHandles_[i].qpHandle, &mrInfo));
    1997              :         }
    1998              :     }
    1999              : 
    2000            0 :     memMsg.mrRegFlag = REG_VALID;
    2001            0 :     memMsg.addr = addr;
    2002            0 :     memMsg.len = size;
    2003            0 :     memMsg.lkey = mrInfo.lkey;
    2004              : 
    2005            0 :     CHK_SAFETY_FUNC_RET(memcpy_s(exchangeDataPtr, exchangeDataBlankSize,
    2006              :         reinterpret_cast<void*>(&memMsg), sizeof(MemMsg)));
    2007              : 
    2008            0 :     exchangeDataPtr += sizeof(MemMsg);
    2009            0 :     exchangeDataBlankSize -= sizeof(MemMsg);
    2010              : 
    2011            0 :     HCCL_DEBUG("mem_ptr=%p mem_size=%llu Byte, key = %u", addr, size, mrInfo.lkey);
    2012              : 
    2013            0 :     return HCCL_SUCCESS;
    2014              : }
    2015              : 
    2016            0 : HcclResult TransportIbverbs::RegCustomUserMem(u8 *&exchangeDataPtr, u64 &exchangeDataBlankSize)
    2017              : {
    2018            0 :     u32 deviceMemNum = machinePara_.userDeviceMem.size();
    2019            0 :     s32 sRet = memcpy_s(exchangeDataPtr, sizeof(u32), 
    2020              :         reinterpret_cast<void*>(&deviceMemNum), sizeof(u32));
    2021            0 :     CHK_PRT_RET(sRet != EOK,
    2022              :         HCCL_ERROR("[Set][LocalMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu],cnt[%zu]",
    2023              :         HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(u32), sizeof(u32)), HCCL_E_MEMORY);
    2024            0 :     exchangeDataPtr += sizeof(u32);
    2025            0 :     exchangeDataBlankSize -= sizeof(u32);
    2026              : 
    2027            0 :     userDeviceMemMsg_.resize(deviceMemNum);
    2028            0 :     for (u32 i = 0; i < deviceMemNum; i++) {
    2029            0 :         RegCustomUserMemWithMsg(machinePara_.userDeviceMem[i].ptr(), 
    2030            0 :             machinePara_.userDeviceMem[i].size(), userDeviceMemMsg_[i], 
    2031              :             exchangeDataPtr, exchangeDataBlankSize);
    2032              :     }
    2033              :     
    2034            0 :     u32 hostMemNum = machinePara_.userHostMem.size();
    2035            0 :     sRet = memcpy_s(exchangeDataPtr, sizeof(u32), 
    2036              :         reinterpret_cast<void*>(&hostMemNum), sizeof(u32));
    2037            0 :     CHK_PRT_RET(sRet != EOK,
    2038              :         HCCL_ERROR("[Set][LocalMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu],cnt[%zu]",
    2039              :         HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(u32), sizeof(u32)), HCCL_E_MEMORY);
    2040            0 :     exchangeDataPtr += sizeof(u32);
    2041            0 :     exchangeDataBlankSize -= sizeof(u32);
    2042              : 
    2043            0 :     userHostMemMsg_.resize(hostMemNum);
    2044            0 :     for (u32 i = 0; i < hostMemNum; i++) {
    2045            0 :         RegCustomUserMemWithMsg(machinePara_.userHostMem[i].ptr(), 
    2046            0 :             machinePara_.userHostMem[i].size(), userHostMemMsg_[i], 
    2047              :             exchangeDataPtr, exchangeDataBlankSize);
    2048              :     }
    2049              : 
    2050            0 :     return HCCL_SUCCESS;
    2051              : }
    2052              : 
    2053            0 : HcclResult TransportIbverbs::GetMemInfo(UserMemType memType, void **dstMemPtr, u64 *dstMemSize)
    2054              : {
    2055            0 :     switch (memType) {
    2056            0 :         case UserMemType::INPUT_MEM: {
    2057            0 :             *dstMemPtr = remoteMemMsg_[static_cast<u32>(MemType::USER_INPUT_MEM)].addr;
    2058            0 :             *dstMemSize = remoteMemMsg_[static_cast<u32>(MemType::USER_INPUT_MEM)].len;
    2059            0 :             break;
    2060              :         }
    2061              : 
    2062            0 :         case UserMemType::OUTPUT_MEM: {
    2063            0 :             *dstMemPtr = remoteMemMsg_[static_cast<u32>(MemType::USER_OUTPUT_MEM)].addr;
    2064            0 :             *dstMemSize = remoteMemMsg_[static_cast<u32>(MemType::USER_OUTPUT_MEM)].len;
    2065            0 :             break;
    2066              :         }
    2067              : 
    2068            0 :         default: {
    2069            0 :             HCCL_ERROR("[Get][MemInfo]not support dst_mem_type=%d", memType);
    2070            0 :             return HCCL_E_NOT_SUPPORT;
    2071              :         }
    2072              :     }
    2073            0 :     return HCCL_SUCCESS;
    2074              : }
    2075              : 
    2076            0 : HcclResult TransportIbverbs::GetRemoteAddr(MemType memType, u8*& exchangeDataPtr, u64& exchangeDataBlankSize)
    2077              : {
    2078            0 :     if (memType != MULTI_QP_DATA_NOTIFY_MEM) {
    2079            0 :         s32 sRet = memcpy_s(&remoteMemMsg_[static_cast<u32>(memType)],
    2080              :             sizeof(MemMsg), exchangeDataPtr, sizeof(MemMsg));
    2081            0 :         CHK_PRT_RET(sRet != EOK, HCCL_ERROR("[Get][RemoteAddr]errNo[0x%016llx] In lbv exp get remote addr, "\
    2082              :             "memcpy failed. errorno[%d], params:destMaxSize[%zu],count[%zu]",
    2083              :             HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(MemMsg), sizeof(MemMsg)), HCCL_E_MEMORY);
    2084            0 :         CHK_PTR_NULL(remoteMemMsg_[static_cast<u32>(memType)].addr);
    2085              :     } else {
    2086            0 :         MemMsg memMsg;
    2087            0 :         s32 sRet = memcpy_s(&memMsg, sizeof(MemMsg), exchangeDataPtr, sizeof(MemMsg));
    2088            0 :         CHK_PRT_RET(sRet != EOK, HCCL_ERROR("[Get][RemoteAddr]errNo[0x%016llx] In lbv exp get remote addr, "\
    2089              :             "memcpy failed. errorno[%d], params:destMaxSize[%zu],count[%zu]",
    2090              :             HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(MemMsg), sizeof(MemMsg)), HCCL_E_MEMORY);
    2091            0 :         CHK_PTR_NULL(memMsg.addr);
    2092            0 :         multiQpDataNotifyRemoteMemMsg_.push_back(std::move(memMsg));
    2093              :     }
    2094              : 
    2095            0 :     exchangeDataPtr += sizeof(MemMsg);
    2096            0 :     exchangeDataBlankSize -= sizeof(MemMsg);
    2097            0 :     HCCL_INFO("GetRemoteAddr success: memType=%d, addr=%p len=%llu, notifyId=%u",
    2098              :         static_cast<int32_t>(memType), remoteMemMsg_[static_cast<u32>(memType)].addr,
    2099              :         remoteMemMsg_[static_cast<u32>(memType)].len, remoteMemMsg_[static_cast<u32>(memType)].notifyId);
    2100            0 :     return HCCL_SUCCESS;
    2101              : }
    2102              : 
    2103            0 : HcclResult TransportIbverbs::GetIndOpRemoteAddr(u8*& exchangeDataPtr, u64& exchangeDataBlankSize)
    2104              : {
    2105            0 :     u32 remoteDmemNum = 0;
    2106            0 :     s32 sRet = memcpy_s(reinterpret_cast<void*>(&remoteDmemNum), sizeof(u32), exchangeDataPtr, sizeof(u32));
    2107            0 :     CHK_PRT_RET(sRet != EOK,
    2108              :         HCCL_ERROR("[Get][RemoteMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu],cnt[%zu]",
    2109              :         HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(u32), sizeof(u32)), HCCL_E_MEMORY);
    2110            0 :     exchangeDataPtr += sizeof(u32);
    2111            0 :     exchangeDataBlankSize -= sizeof(u32);
    2112              : 
    2113            0 :     remoteUserDeviceMemMsg_.resize(remoteDmemNum);
    2114            0 :     for (u32 i = 0; i < remoteDmemNum; i++) {
    2115            0 :         sRet = memcpy_s(&remoteUserDeviceMemMsg_[i], sizeof(MemMsg), exchangeDataPtr, sizeof(MemMsg));
    2116            0 :         CHK_PRT_RET(sRet != EOK, HCCL_ERROR("[Get][GetCustomRemoteAddr]errNo[0x%016llx] In lbv exp get remote addr, "\
    2117              :             "memcpy failed. errorno[%d], params:destMaxSize[%zu],count[%zu]",
    2118              :             HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(MemMsg), sizeof(MemMsg)), HCCL_E_MEMORY);
    2119            0 :         exchangeDataPtr += sizeof(MemMsg);
    2120            0 :         exchangeDataBlankSize -= sizeof(MemMsg);
    2121            0 :         CHK_PTR_NULL(remoteUserDeviceMemMsg_[i].addr);
    2122              :     }
    2123              : 
    2124            0 :     u32 remoteHmemNum = 0;
    2125            0 :     sRet = memcpy_s(reinterpret_cast<void*>(&remoteHmemNum), sizeof(u32), exchangeDataPtr, sizeof(u32));
    2126            0 :     CHK_PRT_RET(sRet != EOK,
    2127              :         HCCL_ERROR("[Get][RemoteMem]errNo[0x%016llx] memory copy failed. errorno[%d], params:dstMaxSize[%zu],cnt[%zu]",
    2128              :         HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(u32), sizeof(u32)), HCCL_E_MEMORY);
    2129            0 :     exchangeDataPtr += sizeof(u32);
    2130            0 :     exchangeDataBlankSize -= sizeof(u32);
    2131              : 
    2132            0 :     remoteUserHostMemMsg_.resize(remoteHmemNum);
    2133            0 :     for (u32 i = 0; i < remoteHmemNum; i++) {
    2134            0 :         sRet = memcpy_s(&remoteUserHostMemMsg_[i], sizeof(MemMsg), exchangeDataPtr, sizeof(MemMsg));
    2135            0 :         CHK_PRT_RET(sRet != EOK, HCCL_ERROR("[Get][GetCustomRemoteAddr]errNo[0x%016llx] In lbv exp get remote addr, "\
    2136              :             "memcpy failed. errorno[%d], params:destMaxSize[%zu],count[%zu]",
    2137              :             HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(MemMsg), sizeof(MemMsg)), HCCL_E_MEMORY);
    2138            0 :         exchangeDataPtr += sizeof(MemMsg);
    2139            0 :         exchangeDataBlankSize -= sizeof(MemMsg);
    2140            0 :         CHK_PTR_NULL(remoteUserHostMemMsg_[i].addr);
    2141              :     }
    2142              : 
    2143            0 :     return HCCL_SUCCESS;
    2144              : }
    2145              : 
    2146            0 : HcclResult TransportIbverbs::GetRemoteNotifyAddr(u8*& exchangeDataPtr, u64& exchangeDataBlankSize, MemMsg& memMsg)
    2147              : {
    2148            0 :     s32 sRet = memcpy_s(&memMsg, sizeof(MemMsg), exchangeDataPtr, sizeof(MemMsg));
    2149            0 :     CHK_PRT_RET(sRet != EOK, HCCL_ERROR("[Get][GetRemoteNotifyAddr]errNo[0x%016llx] In lbv exp get remote addr, "\
    2150              :         "memcpy failed. errorno[%d], params:destMaxSize[%zu],count[%zu]",
    2151              :         HCCL_ERROR_CODE(HCCL_E_MEMORY), sRet, sizeof(MemMsg), sizeof(MemMsg)), HCCL_E_MEMORY);
    2152              : 
    2153            0 :     exchangeDataPtr += sizeof(MemMsg);
    2154            0 :     exchangeDataBlankSize -= sizeof(MemMsg);
    2155            0 :     CHK_PTR_NULL(memMsg.addr);
    2156            0 :     HCCL_INFO("GetRemoteNotifyAddr success: addr=%p len=%llu", memMsg.addr, memMsg.len);
    2157            0 :     return HCCL_SUCCESS;
    2158              : }
    2159              : 
    2160            0 : HcclResult TransportIbverbs::CreateNotifyValueBuffer()
    2161              : {
    2162            0 :     if (!machinePara_.userMemEnable && !machinePara_.drainEnable) {
    2163            0 :         HCCL_INFO("userMemEnable is false, no need to create notify value buffer");
    2164            0 :         return HCCL_SUCCESS;
    2165              :     }
    2166            0 :     std::unique_lock<std::mutex> lock(notifyValueMutex_[machinePara_.deviceLogicId]);
    2167            0 :     if (notifyValueMem_[machinePara_.deviceLogicId].ptr() == nullptr) {
    2168            0 :         u64 notifyVaule = 1; // notify值写1表示record
    2169            0 :         CHK_RET(DeviceMem::alloc(notifyValueMem_[machinePara_.deviceLogicId], notifyValueSize_));
    2170            0 :         HCCL_DEBUG("create notify value buffer[%p], size[%u]", notifyValueMem_[machinePara_.deviceLogicId].ptr(),
    2171              :             notifySize_);
    2172              : 
    2173            0 :         CHK_RET(hrtMemSyncCopy(notifyValueMem_[machinePara_.deviceLogicId].ptr(),
    2174              :             notifyValueMem_[machinePara_.deviceLogicId].size(), &notifyVaule,
    2175              :             notifySize_, HcclRtMemcpyKind::HCCL_RT_MEMCPY_KIND_HOST_TO_DEVICE));
    2176              :     }
    2177            0 :     lock.unlock();
    2178              : 
    2179            0 :     struct MrInfoT mrInfo = {nullptr};
    2180            0 :     mrInfo.addr = notifyValueMem_[machinePara_.deviceLogicId].ptr();
    2181            0 :     mrInfo.size = notifySize_;
    2182            0 :     mrInfo.access = access_;
    2183              :     
    2184            0 :     for (u32 i = 0; i < combineQpHandles_.size(); i++) {
    2185            0 :         CHK_RET(HrtRaMrReg(combineQpHandles_[i].qpHandle, &mrInfo));
    2186              :     }
    2187              :     
    2188            0 :     if (UseMultiQp()) {
    2189            0 :         for (u32 i = 0; i < qpsPerConnection_; i++) {
    2190            0 :             CHK_RET(HrtRaMrReg(multiCombineQpHandles_[i].qpHandle, &mrInfo));
    2191              :         }
    2192              :     }
    2193            0 :     memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)].mrRegFlag = REG_VALID;
    2194            0 :     memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)].addr = notifyValueMem_[machinePara_.deviceLogicId].ptr();
    2195            0 :     memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)].len = notifySize_;
    2196            0 :     memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)].memType = MemType::NOTIFY_SRC_MEM;
    2197            0 :     memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)].lkey = mrInfo.lkey;
    2198              : 
    2199            0 :     HCCL_DEBUG("notifyValueMem_=%p", notifyValueMem_[machinePara_.deviceLogicId].ptr());
    2200              : 
    2201            0 :     return HCCL_SUCCESS;
    2202            0 : }
    2203           34 : void TransportIbverbs::DestroySignal()
    2204              : {
    2205           34 :     dataNotify_ = nullptr;
    2206              : 
    2207           34 :     ackNotify_ = nullptr;
    2208              : 
    2209           34 :     dataAckNotify_ = nullptr;
    2210              : 
    2211           34 :     multiQpDataNotify_.clear();
    2212           34 : }
    2213              : 
    2214              : /* 发送ack消息(同步模式) */
    2215            0 : HcclResult TransportIbverbs::TxPrepare(Stream &stream)
    2216              : {
    2217            0 :     HcclResult ret = LocalIpcNotify::Wait(stream, dispatcher_, ackNotify_, INVALID_VALUE_STAGE,
    2218              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank);
    2219            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
    2220              :         HCCL_ERROR("[TransportIbverbs][TxPrepare]errNo[0x%016llx] In lbv exp rx ack, signal wait failed. ",
    2221              :             HCCL_ERROR_CODE(ret)), ret);
    2222              : 
    2223            0 :     return HCCL_SUCCESS;
    2224              : }
    2225              : 
    2226              : /* 接收ack消息(同步模式) */
    2227            0 : HcclResult TransportIbverbs::RxPrepare(Stream &stream)
    2228              : {
    2229            0 :     CHK_RET(TxSendWqe(remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].addr,
    2230              :         notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_,
    2231              :         stream, WqeType::WQE_TYPE_ACK_NOTIFY));
    2232            0 :     return HCCL_SUCCESS;
    2233              : }
    2234              : 
    2235            0 : HcclResult TransportIbverbs::TxData(UserMemType dstMemType, u64 dstOffset, const void *src, u64 len, Stream &stream)
    2236              : {
    2237            0 :     std::vector<WqeInfo> wqeInfoVec;
    2238            0 :     struct WrAuxInfo aux = {0};
    2239            0 :     HCCL_DEBUG("TX src[%p] len[%llu] dstOffset[%llu]", src, len, dstOffset);
    2240              : 
    2241            0 :     if (src != nullptr) {
    2242            0 :         CHK_RET(TxPayLoad(dstMemType, dstOffset, src, len, WqeType::WQE_TYPE_DATA, aux, wqeInfoVec));
    2243              :     }
    2244              : 
    2245            0 :     if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE) {
    2246            0 :         CHK_RET(RdmaSendAsync(wqeInfoVec, stream, false));
    2247              :     } else {
    2248            0 :         CHK_RET(RdmaSendAsyncHostNIC(wqeInfoVec, stream));
    2249              :     }
    2250            0 :     return HCCL_SUCCESS;
    2251            0 : }
    2252              : 
    2253            0 : HcclResult TransportIbverbs::RxData(UserMemType srcMemType, u64 srcOffset, void *dst, u64 len, Stream &stream)
    2254              : {
    2255            0 :     return HCCL_SUCCESS;
    2256              : }
    2257              : 
    2258            0 : HcclResult TransportIbverbs::TxDone(Stream &stream)
    2259              : {
    2260              :     // 发送数据接收确认notify
    2261            0 :     CHK_RET(TxSendWqe(remoteMemMsg_[static_cast<u32>(MemType::DATA_NOTIFY_MEM)].addr,
    2262              :         notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_, stream, WqeType::WQE_TYPE_DATA_NOTIFY));
    2263              :     // 接收数据接收确认notify
    2264            0 :     CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, dataAckNotify_, INVALID_VALUE_STAGE,
    2265              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    2266            0 :     return HCCL_SUCCESS;
    2267              : }
    2268              : 
    2269            0 : HcclResult TransportIbverbs::RxDone(Stream &stream)
    2270              : {
    2271              :     // 接收数据接收确认notify
    2272            0 :     CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, dataNotify_, INVALID_VALUE_STAGE,
    2273              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    2274              : 
    2275              :     // 发送数据接收确认notify
    2276            0 :     CHK_RET(TxSendWqe(remoteMemMsg_[static_cast<u32>(MemType::DATA_ACK_NOTIFY_MEM)].addr,
    2277              :         notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_, stream, WqeType::WQE_TYPE_DATA_ACK_NOTIFY));
    2278            0 :     return HCCL_SUCCESS;
    2279              : }
    2280              : 
    2281            0 : HcclResult TransportIbverbs::PostReady(Stream &stream)
    2282              : {
    2283            0 :     CHK_RET(TxSendWqe(remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].addr,
    2284              :         notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_,
    2285              :         stream, WqeType::WQE_TYPE_ACK_NOTIFY));
    2286            0 :     return HCCL_SUCCESS;
    2287              : }
    2288              : 
    2289            0 : HcclResult TransportIbverbs::WaitReady(Stream &stream)
    2290              : {
    2291            0 :     CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, ackNotify_, INVALID_VALUE_STAGE,
    2292              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    2293            0 :     return HCCL_SUCCESS;
    2294              : }
    2295              : 
    2296            0 : HcclResult TransportIbverbs::PostFin(Stream &stream)
    2297              : {
    2298              :     // 发送data notify同步信息
    2299            0 :     void *remoteNotifyaddr = remoteDataNotifyMsg_.addr;
    2300            0 :     HcclResult ret = TxSendWqe(remoteNotifyaddr, notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_, stream,
    2301              :         WqeType::WQE_TYPE_DATA_NOTIFY);
    2302            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
    2303              :         HCCL_ERROR("[TransportIbverbs][PostFin]errNo[0x%016llx] In ibv tx data signal, send notify "\
    2304              :         "wqe failed. dstMemPtr[%p], srcMemPtr[%p], srcMemSize[%llu]", HCCL_ERROR_CODE(ret), remoteNotifyaddr,
    2305              :         notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_), ret);
    2306              :     // 每发送一个data notify wqe, count 自增
    2307            0 :     return HCCL_SUCCESS;
    2308              : }
    2309              : 
    2310            0 : HcclResult TransportIbverbs::WaitFin(Stream &stream)
    2311              : {
    2312            0 :     CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, dataNotify_, INVALID_VALUE_STAGE,
    2313              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    2314            0 :     return HCCL_SUCCESS;
    2315              : }
    2316              : 
    2317            0 : HcclResult TransportIbverbs::PostFinAck(Stream &stream)
    2318              : {
    2319            0 :     CHK_RET(TxSendWqe(remoteMemMsg_[static_cast<u32>(MemType::DATA_ACK_NOTIFY_MEM)].addr,
    2320              :         notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_, stream, WqeType::WQE_TYPE_DATA_ACK_NOTIFY));
    2321            0 :     return HCCL_SUCCESS;
    2322              : }
    2323              : 
    2324            0 : HcclResult TransportIbverbs::WaitFinAck(Stream &stream)
    2325              : {
    2326            0 :     CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, dataAckNotify_, INVALID_VALUE_STAGE,
    2327              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    2328            0 :     return HCCL_SUCCESS;
    2329              : }
    2330              : 
    2331            0 : HcclResult TransportIbverbs::Post(u32 notifyIdx, Stream &stream)
    2332              : {
    2333              :     // 校验notifyIdx有效性
    2334            0 :     bool bRet = (notifyIdx >= notifyNum_);
    2335            0 :     CHK_PRT_RET(bRet,
    2336              :         HCCL_ERROR("[TransportIbverbs][Post]notifyNum[%u], notifyIdx[%u] out of range[0, %u]", \
    2337              :         notifyNum_, notifyIdx, notifyNum_-1), HCCL_E_INTERNAL);
    2338              : 
    2339              :     // 每个QP发送一个指定idx的notify
    2340            0 :     for (u32 i = 0; i < qpsPerConnection_; i++) {
    2341            0 :         CHK_RET(TxSendNotifyWqe(userMultiQpRemoteNotifyMsg_[i][notifyIdx],
    2342              :             notifyValueMem_[machinePara_.deviceLogicId].ptr(), notifySize_, stream));
    2343              :     }
    2344            0 :     return HCCL_SUCCESS;
    2345              : }
    2346              : 
    2347            0 : HcclResult TransportIbverbs::Wait(u32 notifyIdx, Stream &stream, const u32 timeOut)
    2348              : {
    2349              :     // 校验notifyIdx有效性
    2350            0 :     bool bRet = (notifyIdx >= notifyNum_);
    2351            0 :     CHK_PRT_RET(bRet,
    2352              :         HCCL_ERROR("[TransportIbverbs][Wait]notifyNum[%u], notifyIdx[%u] out of range[0, %u]", \
    2353              :         notifyNum_, notifyIdx, notifyNum_-1), HCCL_E_INTERNAL);
    2354              : 
    2355              :     //每个qp接收一个指定idx的notify
    2356            0 :     for (u32 i = 0; i < qpsPerConnection_; i++) {
    2357            0 :         CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, userMultiQpLocalNotify_[i][notifyIdx], INVALID_VALUE_STAGE,
    2358              :             timeOut, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    2359              :     }
    2360            0 :     return HCCL_SUCCESS;
    2361              : }
    2362              : 
    2363            0 : HcclResult TransportIbverbs::GetLocalRdmaNotify(std::vector<HcclSignalInfo> &rdmaNotify)
    2364              : {
    2365              :     HcclSignalInfo signalInfo;
    2366            0 :     CHK_SMART_PTR_NULL(ackNotify_);
    2367            0 :     CHK_RET(ackNotify_->GetNotifyData(signalInfo));
    2368            0 :     rdmaNotify.push_back(signalInfo);
    2369            0 :     CHK_SMART_PTR_NULL(ackNotify_);
    2370            0 :     CHK_RET(dataNotify_->GetNotifyData(signalInfo));
    2371            0 :     rdmaNotify.push_back(signalInfo);
    2372            0 :     CHK_SMART_PTR_NULL(ackNotify_);
    2373            0 :     CHK_RET(dataAckNotify_->GetNotifyData(signalInfo));
    2374            0 :     rdmaNotify.push_back(signalInfo);
    2375              :     // 提取新增的notify资源
    2376            0 :     for (u32 i = 0; i < qpsPerConnection_; i++) {
    2377            0 :         for (u32 j = 0; j < notifyNum_; j++) {
    2378            0 :             CHK_SMART_PTR_NULL(userMultiQpLocalNotify_[i][j]);
    2379            0 :             CHK_RET(userMultiQpLocalNotify_[i][j]->GetNotifyData(signalInfo));
    2380            0 :             rdmaNotify.push_back(signalInfo);
    2381              :         }
    2382            0 :         if (qpsPerConnection_ > 1) {
    2383            0 :             CHK_SMART_PTR_NULL(multiQpDataNotify_[i]);
    2384            0 :             CHK_RET(multiQpDataNotify_[i]->GetNotifyData(signalInfo));
    2385            0 :             rdmaNotify.push_back(signalInfo);
    2386              :         }
    2387            0 :         HCCL_DEBUG("[TransportIbverbs][GetLocalRdmaNotify] resId[%llu] addr[%llu]",
    2388              :             rdmaNotify.back().resId,
    2389              :             rdmaNotify.back().addr);
    2390              :     }
    2391            0 :     return HCCL_SUCCESS;
    2392              : }
    2393              : 
    2394            0 : HcclResult TransportIbverbs::GetRemoteRdmaNotifyAddrKey(std::vector<AddrKey> &rdmaNotify)
    2395              : {
    2396            0 :     if (remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].addr == nullptr) {
    2397            0 :         HCCL_ERROR("[TransportIbverbs][GetRemoteRdmaNotifyAddrKey] ackNotify is null!");
    2398            0 :         return HCCL_E_PTR;
    2399            0 :     } else if (remoteMemMsg_[static_cast<u32>(MemType::DATA_NOTIFY_MEM)].addr == nullptr) {
    2400            0 :         HCCL_ERROR("[TransportIbverbs][GetRemoteRdmaNotifyAddrKey] dataNotify is null!");
    2401            0 :         return HCCL_E_PTR;
    2402            0 :     } else if (remoteMemMsg_[static_cast<u32>(MemType::DATA_ACK_NOTIFY_MEM)].addr == nullptr) {
    2403            0 :         HCCL_ERROR("[TransportIbverbs][GetRemoteRdmaNotifyAddrKey] dataAckNotify is null!");
    2404            0 :         return HCCL_E_PTR;
    2405              :     }
    2406            0 :     AddrKey notifyDetails;
    2407            0 :     notifyDetails.addr = reinterpret_cast<u64>(remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].addr);
    2408            0 :     notifyDetails.key = reinterpret_cast<u32>(remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].lkey);
    2409            0 :     notifyDetails.notifyId = remoteMemMsg_[static_cast<u32>(MemType::ACK_NOTIFY_MEM)].notifyId;
    2410            0 :     rdmaNotify.push_back(notifyDetails);
    2411            0 :     notifyDetails.addr = reinterpret_cast<u64>(remoteMemMsg_[static_cast<u32>(MemType::DATA_NOTIFY_MEM)].addr);
    2412            0 :     notifyDetails.key = reinterpret_cast<u32>(remoteMemMsg_[static_cast<u32>(MemType::DATA_NOTIFY_MEM)].lkey);
    2413            0 :     notifyDetails.notifyId = remoteMemMsg_[static_cast<u32>(MemType::DATA_NOTIFY_MEM)].notifyId;
    2414            0 :     rdmaNotify.push_back(notifyDetails);
    2415            0 :     notifyDetails.addr = reinterpret_cast<u64>(remoteMemMsg_[static_cast<u32>(MemType::DATA_ACK_NOTIFY_MEM)].addr);
    2416            0 :     notifyDetails.key = reinterpret_cast<u32>(remoteMemMsg_[static_cast<u32>(MemType::DATA_ACK_NOTIFY_MEM)].lkey);
    2417            0 :     notifyDetails.notifyId = remoteMemMsg_[static_cast<u32>(MemType::DATA_ACK_NOTIFY_MEM)].notifyId;
    2418            0 :     rdmaNotify.push_back(notifyDetails);
    2419              : 
    2420              :     // 获取新增的多notify资源
    2421            0 :     for (u32 i = 0; i < qpsPerConnection_; i++) {
    2422            0 :         for (u32 j = 0; j < notifyNum_; j++) {
    2423            0 :             notifyDetails.addr = reinterpret_cast<u64>(userMultiQpRemoteNotifyMsg_[i][j].addr);
    2424            0 :             notifyDetails.key = reinterpret_cast<u32>(userMultiQpRemoteNotifyMsg_[i][j].lkey);
    2425            0 :             notifyDetails.notifyId = userMultiQpRemoteNotifyMsg_[i][j].notifyId;
    2426            0 :             rdmaNotify.push_back(notifyDetails);
    2427              :         }
    2428            0 :         if (qpsPerConnection_ > 1) {
    2429            0 :             notifyDetails.addr = reinterpret_cast<u64>(multiQpDataNotifyRemoteMemMsg_[i].addr);
    2430            0 :             notifyDetails.key = reinterpret_cast<u32>(multiQpDataNotifyRemoteMemMsg_[i].lkey);
    2431            0 :             notifyDetails.notifyId = multiQpDataNotifyRemoteMemMsg_[i].notifyId;
    2432            0 :             rdmaNotify.push_back(notifyDetails);
    2433              :         }
    2434            0 :         HCCL_DEBUG("[TransportIbverbs][GetRemoteRdmaNotifyAddrKey]remote addr[0x%llx], key[%lu], notifyId[%u]",
    2435              :             rdmaNotify.back().addr, rdmaNotify.back().key, rdmaNotify.back().notifyId);
    2436              :     }
    2437            0 :     return HCCL_SUCCESS;
    2438              : }
    2439              : 
    2440            0 : HcclResult TransportIbverbs::GetLocalNotifyValueAddrKey(std::vector<AddrKey> &notifyValue)
    2441              : {
    2442            0 :     if (memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)].addr == nullptr) {
    2443            0 :         HCCL_ERROR("[TransportIbverbs][GetLocalNotifyValueAddrKey] notifyValue is null!");
    2444            0 :         return HCCL_E_PTR;
    2445              :     }
    2446              : 
    2447            0 :     AddrKey notifyDetails;
    2448            0 :     notifyDetails.addr = reinterpret_cast<u64>(memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)].addr);
    2449            0 :     notifyDetails.key = reinterpret_cast<u32>(memMsg_[static_cast<u32>(MemType::NOTIFY_SRC_MEM)].lkey);
    2450            0 :     notifyValue.push_back(notifyDetails);
    2451            0 :     return HCCL_SUCCESS;
    2452              : }
    2453              : 
    2454            0 : HcclResult TransportIbverbs::GetRemoteMemKey(UserMemType memType, uint32_t *remoteMemKey)
    2455              : {
    2456            0 :     switch (memType) {
    2457            0 :         case UserMemType::INPUT_MEM:
    2458              :         case UserMemType::OUTPUT_MEM:
    2459            0 :             *remoteMemKey = remoteMemMsg_[static_cast<u32>(memType)].lkey;
    2460            0 :             break;
    2461              : 
    2462            0 :         default:
    2463            0 :             HCCL_ERROR("[Get][RemoteMemKey]not support dst_mem_type=%d", memType);
    2464            0 :             return HCCL_E_NOT_SUPPORT;
    2465              :     }
    2466            0 :     return HCCL_SUCCESS;
    2467              : }
    2468              : 
    2469            0 : HcclResult TransportIbverbs::GetLocalMemDetails(UserMemType memType, MemDetails &memDetails)
    2470              : {
    2471            0 :     switch (memType) {
    2472            0 :         case UserMemType::INPUT_MEM:
    2473              :         case UserMemType::OUTPUT_MEM:
    2474            0 :             memDetails.addr = reinterpret_cast<u64>(memMsg_[static_cast<u32>(memType)].addr);
    2475            0 :             memDetails.size = memMsg_[static_cast<u32>(memType)].len;
    2476            0 :             memDetails.key = memMsg_[static_cast<u32>(memType)].lkey;
    2477            0 :             break;
    2478              : 
    2479            0 :         default:
    2480            0 :             HCCL_ERROR("[Get][LocalMemDetails]not support dst_mem_type=%d", memType);
    2481            0 :             return HCCL_E_NOT_SUPPORT;
    2482              :     }
    2483            0 :     return HCCL_SUCCESS;
    2484              : }
    2485              : 
    2486            0 : HcclResult TransportIbverbs::GetAiQpInfo(std::vector<HcclQpInfoV2> &aiQpInfo)
    2487              : {
    2488            0 :     aiQpInfo.resize(combineAiQpInfos_.size() + 1);
    2489              : 
    2490            0 :     aiQpInfo[0].qpPtr   = combineAiQpInfo_.aiQpInfo.aiQpAddr;
    2491            0 :     aiQpInfo[0].sqIndex = combineAiQpInfo_.aiQpInfo.sqIndex;
    2492            0 :     aiQpInfo[0].dbIndex = combineAiQpInfo_.aiQpInfo.dbIndex;
    2493            0 :     HCCL_DEBUG("[TransportIbverbs][GetAiQpInfo] i[0] qpPtr[%llu] sqIndex[%u] dbIndex[%u]",
    2494              :         aiQpInfo[0].qpPtr, aiQpInfo[0].sqIndex, aiQpInfo[0].dbIndex);
    2495            0 :     for (u32 i = 1, j = 0; i < aiQpInfo.size(); i++, j++) {
    2496            0 :         aiQpInfo[i].qpPtr = combineAiQpInfos_[j].aiQpInfo.aiQpAddr;
    2497            0 :         aiQpInfo[i].sqIndex = combineAiQpInfos_[j].aiQpInfo.sqIndex;
    2498            0 :         aiQpInfo[i].dbIndex = combineAiQpInfos_[j].aiQpInfo.dbIndex;
    2499            0 :         HCCL_DEBUG("[TransportIbverbs][GetAiQpInfo] i[%u] qpPtr[%llu] sqIndex[%u] dbIndex[%u]",
    2500              :             i, aiQpInfo[i].qpPtr, aiQpInfo[i].sqIndex, aiQpInfo[i].dbIndex);
    2501              :     }
    2502            0 :     return HCCL_SUCCESS;
    2503              : }
    2504              : 
    2505            0 : HcclResult TransportIbverbs::GetAiRMAQueueInfo(std::vector<HcclAiRMAQueueInfo> &aiRMAQueueInfo)
    2506              : {
    2507            0 :     bool isSupport = false;
    2508            0 :     CHK_RET(IsSupportAIVNormalQP(machinePara_.localDeviceId, isSupport));
    2509            0 :     CHK_PRT_RET(isSupport == false, HCCL_ERROR("[IsSupportCQCoverNormalQP]"
    2510              :         "devicePhyId[%u] not support" , machinePara_.localDeviceId), HCCL_E_NOT_SUPPORT);
    2511              : 
    2512            0 :     u32 sl = GetExternalInputRdmaServerLevel();
    2513            0 :     if (machinePara_.sl != HCCL_COMM_SERVICE_LEVEL_CONFIG_NOT_SET) {
    2514            0 :         sl = machinePara_.sl;
    2515              :     }
    2516            0 :     HCCL_INFO("[TransportIbverbs][GetAiRMAQueueInfo] localUserRank[%u], remoteUserrank[%u], sl[%u]",
    2517              :         machinePara_.localUserrank, machinePara_.remoteUserrank, sl);
    2518            0 :     aiRMAQueueInfo.resize(combineAiQpInfos_.size() + 1);
    2519            0 :     CopyAiWQInfo(aiRMAQueueInfo[0].sq, combineAiQpInfo_.aiQpInfo.dataPlaneInfo.sq, DBMode::HW_DB, sl);
    2520            0 :     CopyAiWQInfo(aiRMAQueueInfo[0].rq, combineAiQpInfo_.aiQpInfo.dataPlaneInfo.rq, DBMode::SW_DB, sl);
    2521            0 :     CopyAiCQInfo(aiRMAQueueInfo[0].scq, combineAiQpInfo_.aiQpInfo.dataPlaneInfo.scq, DBMode::SW_DB);
    2522            0 :     CopyAiCQInfo(aiRMAQueueInfo[0].rcq, combineAiQpInfo_.aiQpInfo.dataPlaneInfo.rcq, DBMode::SW_DB);
    2523              :  
    2524              :     // 预留多QP的能力; 当前主要是单QP场景
    2525            0 :     for (u32 i = 1, j = 0; i < aiRMAQueueInfo.size(); i++, j++) {
    2526            0 :         CopyAiWQInfo(aiRMAQueueInfo[i].sq, combineAiQpInfos_[j].aiQpInfo.dataPlaneInfo.sq, DBMode::HW_DB, sl);
    2527            0 :         CopyAiWQInfo(aiRMAQueueInfo[i].rq, combineAiQpInfos_[j].aiQpInfo.dataPlaneInfo.rq, DBMode::SW_DB, sl);
    2528            0 :         CopyAiCQInfo(aiRMAQueueInfo[i].scq, combineAiQpInfos_[j].aiQpInfo.dataPlaneInfo.scq, DBMode::SW_DB);
    2529            0 :         CopyAiCQInfo(aiRMAQueueInfo[i].rcq, combineAiQpInfos_[j].aiQpInfo.dataPlaneInfo.rcq, DBMode::SW_DB);
    2530              :     }
    2531            0 :     return HCCL_SUCCESS;
    2532              : }
    2533              : 
    2534            0 : HcclResult TransportIbverbs::WriteCommon(const void *remoteAddr, const void *localAddr, u64 length, Stream &stream,
    2535              :     WqeType wqeType, struct WrAuxInfo &aux)
    2536              : {
    2537              :     // 单qp & 多qp
    2538            0 :     std::vector<WqeInfo> wqeInfoVec;
    2539            0 :     wqeInfoVec.reserve(WQE_RESERVE_LENGTH);
    2540            0 :     HCCL_DEBUG("write localAddr[%p] remoteAddr[%p] len[%llu] remoteOffset[%llu]",
    2541              :         localAddr, remoteAddr, length);
    2542              : 
    2543            0 :     if (localAddr != nullptr) {
    2544              :         // 为保证单算子下不同数据量下子图的结构相同,zero byte message 时也需要下发task
    2545            0 :         u32 txSendDataTimes = (length == 0) ? 1 : (length + RDMA_SEND_MAX_SIZE - 1) / RDMA_SEND_MAX_SIZE;
    2546            0 :         CHK_RET(ConstructPayLoadWqe(const_cast<void *>(remoteAddr),
    2547              :             const_cast<void *>(localAddr),
    2548              :             length,
    2549              :             wqeType,
    2550              :             aux,
    2551              :             wqeInfoVec,
    2552              :             txSendDataTimes));
    2553              :     }
    2554              : 
    2555            0 :     u32 maxLength = 0;
    2556            0 :     for (u32 i = 0; i < wqeInfoVec.size(); i++) {
    2557            0 :         if (wqeInfoVec[i].wqeData.memList.len > maxLength) {
    2558            0 :             maxLength = wqeInfoVec[i].wqeData.memList.len;
    2559              :         }
    2560              :     }
    2561              :     
    2562            0 :     u32 actualMultiQpNum = GetActualQpNum(maxLength);
    2563              : 
    2564            0 :     HCCL_DEBUG("[TransportIbverbs][TxSendDataAndNotify] UseMultiQp[%d] MultiQpNum[%u] actualMultiQpNum[%u] maxLength[%u]",
    2565              :         UseMultiQp(), qpsPerConnection_, actualMultiQpNum, maxLength);
    2566            0 :     if (UseMultiQp() && actualMultiQpNum != 1 && actualMultiQpNum <= qpsPerConnection_ && maxLength != 0) {
    2567            0 :             std::vector<std::vector<WqeInfo>> multiQpWqeInfoVct(actualMultiQpNum, wqeInfoVec);
    2568            0 :         for (u32 i = 0; i < wqeInfoVec.size(); i++) {
    2569            0 :             WqeInfo tmpWqeInfo = wqeInfoVec[i];
    2570            0 :             u32 curLen = tmpWqeInfo.wqeData.memList.len;
    2571            0 :             std::vector<u32> splittedLen = RdmaLengthSplit(curLen, actualMultiQpNum);
    2572            0 :             uint64_t curSrcAddr = tmpWqeInfo.wqeData.memList.addr;
    2573            0 :             uint64_t curDstAddr = tmpWqeInfo.wqeData.dstAddr;
    2574            0 :             for (u32 qpIndex = 0; qpIndex < actualMultiQpNum; qpIndex++) {
    2575            0 :                 multiQpWqeInfoVct[qpIndex][i].wqeData.memList.len = splittedLen[qpIndex];
    2576            0 :                 multiQpWqeInfoVct[qpIndex][i].wqeData.memList.addr = curSrcAddr;
    2577            0 :                 multiQpWqeInfoVct[qpIndex][i].wqeData.dstAddr = curDstAddr;
    2578            0 :                 curSrcAddr += splittedLen[qpIndex];
    2579            0 :                 curDstAddr += splittedLen[qpIndex];
    2580              :             }
    2581            0 :         }
    2582              : 
    2583              :         // useOneDoorbell 配置成true。最后一个payload去按doorbell
    2584            0 :         for (u32 qpIndex = 0; qpIndex < actualMultiQpNum; qpIndex++) {
    2585            0 :             CHK_RET(RdmaSendAsync(multiQpWqeInfoVct[qpIndex], stream, true, qpIndex)); // 多QP使用同一个stream异步doorbell触发
    2586              :         }
    2587            0 :     } else {
    2588            0 :         if (machinePara_.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE) {
    2589            0 :             CHK_RET(RdmaSendAsync(wqeInfoVec, stream, GetUseOneDoorbellValue()));
    2590              :         } else {
    2591            0 :             CHK_RET(RdmaSendAsyncHostNIC(wqeInfoVec, stream));
    2592              :         }
    2593              :     }
    2594            0 :     return HCCL_SUCCESS;
    2595            0 : }
    2596              : 
    2597            0 : HcclResult TransportIbverbs::WriteAsync(
    2598              :     struct Transport::Buffer &remoteBuf, struct Transport::Buffer &localBuf, Stream &stream)
    2599              : {
    2600            0 :     struct WrAuxInfo aux = {0};
    2601            0 :     return WriteCommon(remoteBuf.addr, localBuf.addr, remoteBuf.size, stream, WqeType::WQE_TYPE_DATA, aux);
    2602              : }
    2603              : 
    2604            0 : HcclResult TransportIbverbs::WriteReduceAsync(struct Transport::Buffer &remoteBuf, struct Transport::Buffer &localBuf,
    2605              :     const HcclDataType datatype, HcclReduceOp redOp, Stream &stream)
    2606              : {
    2607            0 :     struct WrAuxInfo aux = {0};
    2608            0 :     aux.dataType = RDMA_REDUCE_DATA_TYPE_TABLE[datatype];
    2609            0 :     aux.reduceType = RDMA_REDUCE_OP_TYPE_TABLE[redOp];
    2610            0 :     if (aux.dataType == static_cast<uint8_t>(RdmaReduceDataType::RDMA_REDUCE_DATA_INVALID) ||
    2611            0 :         aux.reduceType == static_cast<uint8_t>(RdmaReduceOpType::RDMA_REDUCE_OP_INVALID)) {
    2612            0 :         HCCL_ERROR("unsupported data type [%s] or Reduce type [%s]",
    2613              :             GetDataTypeEnumStr(datatype).c_str(), GetReduceOpEnumStr(redOp).c_str());
    2614            0 :         return HCCL_E_INTERNAL;
    2615              :     }
    2616              : 
    2617            0 :     return WriteCommon(remoteBuf.addr, localBuf.addr, remoteBuf.size, stream, WqeType::WQE_TYPE_DATA_WITH_REDUCE, aux);
    2618              : }
    2619              : 
    2620            0 : HcclResult TransportIbverbs::WriteSync(
    2621              :     struct Transport::Buffer &remoteBuf, struct Transport::Buffer &localBuf, Stream &stream)
    2622              : {
    2623            0 :     return HCCL_E_NOT_SUPPORT;
    2624              : }
    2625              : 
    2626            0 : HcclResult TransportIbverbs::ReadAsync(
    2627              :     struct Transport::Buffer &localBuf, struct Transport::Buffer &remoteBuf, Stream &stream)
    2628              : {
    2629            0 :     struct WrAuxInfo aux = {0};
    2630            0 :     return WriteCommon(remoteBuf.addr, localBuf.addr, remoteBuf.size, stream, WqeType::WQE_TYPE_READ_DATA, aux);
    2631              : }
    2632              : 
    2633            0 : HcclResult TransportIbverbs::ReadSync(
    2634              :     struct Transport::Buffer &localBuf, struct Transport::Buffer &remoteBuf, Stream &stream)
    2635              : {
    2636            0 :     return HCCL_E_NOT_SUPPORT;
    2637              : }
    2638              : 
    2639            0 : HcclResult TransportIbverbs::GetLocalNotify(std::vector<HcclSignalInfo> &localNotify)
    2640              : {
    2641              :     HcclSignalInfo notifyInfo;
    2642            0 :     CHK_SMART_PTR_NULL(dataNotify_);
    2643            0 :     CHK_RET(dataNotify_->GetNotifyData(notifyInfo));
    2644            0 :     localNotify.push_back(notifyInfo);
    2645              : 
    2646            0 :     CHK_SMART_PTR_NULL(ackNotify_);
    2647            0 :     CHK_RET(ackNotify_->GetNotifyData(notifyInfo));
    2648            0 :     localNotify.push_back(notifyInfo);
    2649              : 
    2650            0 :     CHK_SMART_PTR_NULL(dataAckNotify_);
    2651            0 :     CHK_RET(dataAckNotify_->GetNotifyData(notifyInfo));
    2652            0 :     localNotify.push_back(notifyInfo);
    2653              : 
    2654              :     // 提取新增的notify资源
    2655            0 :     for (u32 i = 0; i < qpsPerConnection_; i++) {
    2656            0 :         for (u32 j = 0; j < notifyNum_; j++) {
    2657            0 :             CHK_SMART_PTR_NULL(userMultiQpLocalNotify_[i][j]);
    2658            0 :             CHK_RET(userMultiQpLocalNotify_[i][j]->GetNotifyData(notifyInfo));
    2659            0 :             localNotify.push_back(notifyInfo);
    2660              :         }
    2661              :     }
    2662              : 
    2663            0 :     return HCCL_SUCCESS;
    2664              : }
    2665              : 
    2666           14 : HcclResult TransportIbverbs::GetTransportErrorCqe(const HcclNetDevCtx netDevCtx,
    2667              :     std::vector<std::pair<TransportBase*, CqeInfo>> &infos, u32 &num)
    2668              : {
    2669           14 :     if (g_qpn2IbversLinkMap_.Size() == 0) {
    2670           14 :         num = 0;
    2671           14 :         return HCCL_SUCCESS;
    2672              :     }
    2673              : 
    2674            0 :     if (UNLIKELY(!g_flag)) {
    2675            0 :         CHK_RET(IsSuppCqeErrInfoListConfig(g_isSupCqeErrInfoListConfig));
    2676            0 :         g_flag = true;
    2677              :     }
    2678              : 
    2679            0 :     CHK_PTR_NULL(netDevCtx);
    2680            0 :     s32 deviceLogicId       = (static_cast<NetDevContext *>(netDevCtx))->GetLogicId();
    2681            0 :     s32 devicePhyId         = (static_cast<NetDevContext *>(netDevCtx))->GetPhyId();
    2682            0 :     HcclIpAddress localIp   = (static_cast<NetDevContext *>(netDevCtx))->GetLocalIp();
    2683            0 :     NicType nicType         = (static_cast<NetDevContext *>(netDevCtx))->GetNicType();
    2684            0 :     CHK_PRT_RET(nicType == NicType::HOST_NIC_TYPE,
    2685              :         HCCL_WARNING("[TransportIbverbs][GetTransportErrorCqe] nicType[%d] not support", nicType), HCCL_SUCCESS);
    2686            0 :     RaResourceInfo raResourceInfo;
    2687            0 :     CHK_RET(NetworkManager::GetInstance(deviceLogicId).GetRaResourceInfo(raResourceInfo));
    2688            0 :     RdmaHandle rdmaHandle   = raResourceInfo.nicSocketMap[localIp].nicRdmaHandle;
    2689            0 :     CHK_PTR_NULL(rdmaHandle);
    2690              : 
    2691            0 :     if (g_isSupCqeErrInfoListConfig) {
    2692            0 :         u32 loop = 0;
    2693            0 :         if (num > CQE_ARRAY_SIZE) {
    2694            0 :             loop = (num % CQE_ARRAY_SIZE) ? (num / CQE_ARRAY_SIZE) : ((num / CQE_ARRAY_SIZE) - 1);
    2695              :         }
    2696              : 
    2697            0 :         struct CqeErrInfo infolist[CQE_ARRAY_SIZE] = {};
    2698            0 :         u32 cqeNum = CQE_ARRAY_SIZE;
    2699            0 :         for (u32 index = 0; index <= loop; index++) {
    2700            0 :             cqeNum = (index == loop) ? (num - index * CQE_ARRAY_SIZE) : CQE_ARRAY_SIZE;
    2701            0 :             u32 temNum = cqeNum;
    2702            0 :             CHK_RET(hrtRaGetCqeErrInfoList(rdmaHandle, infolist, &temNum));
    2703            0 :             ProcessCqeInfo(devicePhyId, infolist, temNum, infos);
    2704            0 :             if (temNum < cqeNum) {
    2705            0 :                 break;
    2706              :             }
    2707              :         }
    2708              :     } else {
    2709            0 :         struct CqeErrInfo infolist[1] = {};
    2710            0 :         CHK_RET(hrtRaGetCqeErrInfo(devicePhyId, &infolist[0]));
    2711            0 :         if (infolist[0].status == 0) {
    2712            0 :             num = 0;
    2713            0 :             return HCCL_SUCCESS;
    2714              :         }
    2715            0 :         u32 cqeNum = 1;
    2716            0 :         ProcessCqeInfo(devicePhyId, infolist, cqeNum, infos);
    2717              :     }
    2718              : 
    2719            0 :     num = infos.size();
    2720              : 
    2721            0 :     return HCCL_SUCCESS;
    2722            0 : }
    2723              : 
    2724            0 : void TransportIbverbs::ProcessCqeInfo(const s32 deviceId, const struct CqeErrInfo *infolist, const u32 cqeNum,
    2725              :     std::vector<std::pair<TransportBase*, CqeInfo>> &infos)
    2726              : {
    2727            0 :     for (u32 i = 0; i < cqeNum; i++) {
    2728              :         // localPhyId + qpn
    2729            0 :         auto it = g_qpn2IbversLinkMap_.Find(((static_cast<u64>(deviceId) << DEV_PHY_ID_BIT) | infolist[i].qpn));
    2730            0 :         if (it.second) {
    2731            0 :             TransportBase *ptr = reinterpret_cast<TransportBase*>(it.first->second);
    2732            0 :             infos.push_back(std::make_pair(
    2733              :                 ptr,
    2734            0 :                 CqeInfo(infolist[i].time, infolist[i].status, it.first->second->GetRemoteIp())));
    2735            0 :                 cqeErrQpn_ = infolist[i].qpn;
    2736              :         } else {
    2737            0 :             HCCL_RUN_WARNING("[GetTransportErrorCqe]get err failed, transport is not find.");
    2738              :         }
    2739              :     }
    2740            0 :     return;
    2741              : }
    2742              : 
    2743            0 : HcclIpAddress& TransportIbverbs::GetRemoteIp()
    2744              : {
    2745            0 :     return machinePara_.remoteIpAddr;
    2746              : }
    2747              : 
    2748            0 : HcclResult TransportIbverbs::GetTransportId(u32 &id)
    2749              : {
    2750            0 :     id = cqeErrQpn_;
    2751            0 :     return HCCL_SUCCESS;
    2752              : }
    2753              : 
    2754            0 : HcclResult TransportIbverbs::ExchangeCapabilityHybrid()
    2755              : {
    2756            0 :     HCCL_INFO("[Hybrid][TransportIbverbs] Starting capability exchange");
    2757              : 
    2758              :     // 1. 构造本地能力信息(使用公共头文件中的默认值)
    2759              :     using namespace hcomm;
    2760              :     RoCECapability localCap;
    2761            0 :     localCap.InitDefaults();
    2762            0 :     localCap.nicDeploy = NICDeployment::NIC_DEPLOYMENT_DEVICE;
    2763            0 :     localCap.commStack = CommStackType::COMM_STACK_TRANSPORT_IBVERBS;
    2764              : 
    2765              :     // 2. 发送本地能力(合并为单次发送:totalLength已包含结构体大小)
    2766            0 :     CHK_RET(defaultSocket_->Send(&localCap, sizeof(localCap)));
    2767            0 :     HCCL_INFO("[Hybrid][TransportIbverbs] Sent capability, version=%u", localCap.version);
    2768              : 
    2769              :     // 3. 接收对端能力(单次接收)
    2770              :     RoCECapability recvCap;
    2771            0 :     CHK_RET(defaultSocket_->Recv(&recvCap, sizeof(recvCap)));
    2772              : 
    2773              :     // 4. 先检查魔数,如果不对可能是旧版本,需要回退
    2774            0 :     if (!RoCECapability::CheckMagic(reinterpret_cast<uint8_t*>(&recvCap), sizeof(recvCap))) {
    2775            0 :         HCCL_WARNING("[Hybrid][TransportIbverbs] Magic mismatch, peer may be old version. "
    2776              :                      "Falling back to native mode.");
    2777              :         // 回退到原生模式
    2778            0 :         isHybridMode_ = false;
    2779            0 :         return HCCL_SUCCESS;
    2780              :     }
    2781              : 
    2782              :     // 5. 魔数正确,解析对端能力
    2783              :     RoCECapability remoteCap;
    2784            0 :     if (!remoteCap.Deserialize(reinterpret_cast<uint8_t*>(&recvCap), sizeof(recvCap))) {
    2785            0 :         HCCL_ERROR("[Hybrid][TransportIbverbs] Failed to deserialize capability");
    2786            0 :         return HCCL_E_PARA;
    2787              :     }
    2788              : 
    2789              :     // 6. 校验字段有效性
    2790            0 :     if (!remoteCap.Validate()) {
    2791            0 :         HCCL_ERROR("[Hybrid][TransportIbverbs] Capability validation failed");
    2792            0 :         return HCCL_E_INTERNAL;
    2793              :     }
    2794              : 
    2795              :     // 7. 版本兼容性处理(高版本兼容低版本)
    2796            0 :     if (remoteCap.version > ROCE_CAPABILITY_VERSION) {
    2797              :         // 对端版本更高,使用本地版本的功能集(最小公分母)
    2798            0 :         HCCL_INFO("[Hybrid][TransportIbverbs] Remote version %u > local %u, using local version features",
    2799              :             remoteCap.version, ROCE_CAPABILITY_VERSION);
    2800            0 :     } else if (remoteCap.version < ROCE_CAPABILITY_VERSION) {
    2801              :         // 对端版本更低,使用对端版本的功能集(向下兼容)
    2802            0 :         HCCL_INFO("[Hybrid][TransportIbverbs] Remote version %u < local %u, using remote version features",
    2803              :             remoteCap.version, ROCE_CAPABILITY_VERSION);
    2804              :     }
    2805              : 
    2806            0 :     isHybridMode_ = (remoteCap.commStack == CommStackType::COMM_STACK_HOST_CPU_ROCE) ? true : false;
    2807            0 :     HCCL_INFO("[Hybrid][TransportIbverbs]Exchange mode success, Remote is %s", isHybridMode_ ? "HostCpuRoceChannel" :
    2808              :         "TransportIbverbs");
    2809              : 
    2810            0 :     return HCCL_SUCCESS;
    2811              : }
    2812              : 
    2813            0 : HcclResult TransportIbverbs::GetDrainRemSrcMem(void* &remoteAddr, uint32_t &remoteKey, uint32_t &size)
    2814              : {
    2815            0 :     auto opType = static_cast<u32>(MemType::NOTIFY_SRC_MEM);
    2816            0 :     remoteAddr = remoteMemMsg_[opType].addr;
    2817            0 :     remoteKey = remoteMemMsg_[opType].lkey;
    2818            0 :     size = remoteMemMsg_[opType].len;
    2819            0 :     return HCCL_SUCCESS;
    2820              : }
    2821              : 
    2822            1 : HcclResult TransportIbverbs::Drain(Stream &stream)
    2823              : {
    2824            1 :     auto remoteType = static_cast<u32>(MemType::NOTIFY_SRC_MEM);
    2825            1 :     auto localType = static_cast<u32>(MemType::DATA_NOTIFY_MEM);
    2826            1 :     CHK_PTR_NULL(memMsg_[localType].addr);
    2827            1 :     CHK_PTR_NULL(remoteMemMsg_[remoteType].addr);
    2828            1 :     CHK_RET(Fence());
    2829            1 :     std::vector<WqeInfo> wqeInfoVec;
    2830            1 :     WrAuxInfo aux = {};
    2831            1 :     CHK_RET(AddWqeList(remoteMemMsg_[remoteType].addr,
    2832              :         memMsg_[localType].addr, memMsg_[localType].len,
    2833              :         WqeType::WQE_TYPE_READ_DATA, aux, wqeInfoVec));
    2834            1 :     CHK_RET(RdmaSendAsync(wqeInfoVec, stream, false));
    2835            0 :     CHK_SMART_PTR_NULL(dataNotify_);
    2836            0 :     CHK_RET(LocalIpcNotify::Wait(stream, dispatcher_, dataNotify_, INVALID_VALUE_STAGE,
    2837              :         NOTIFY_INVALID_WAIT_TIME, machinePara_.localUserrank, machinePara_.remoteWorldRank));
    2838            0 :     return HCCL_SUCCESS;
    2839            1 : }
    2840              : 
    2841            0 : HcclResult TransportIbverbs::GetDrainLocalDataNotify(void* &localAddr, uint32_t& lkey, HcclSignalInfo &dataNotify)
    2842              : {
    2843            0 :     localAddr = memMsg_[DATA_NOTIFY_MEM].addr;
    2844            0 :     lkey = memMsg_[DATA_NOTIFY_MEM].lkey;
    2845            0 :     CHK_SMART_PTR_NULL(dataNotify_);
    2846            0 :     CHK_RET(dataNotify_->GetNotifyData(dataNotify));
    2847            0 :     return HCCL_SUCCESS;
    2848              : }
    2849              : }  // namespace hccl
        

Generated by: LCOV version 2.0-1