LCOV - code coverage report
Current view: top level - base_comm/primitives/api_c_adpt - hcomm_channel_c_adpt.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 68.9 % 366 252
Test Date: 2026-08-29 17:38:31 Functions: 75.0 % 28 21

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include <cstring>
      12              : #include <chrono>
      13              : #include <vector>
      14              : 
      15              : #include "hcomm_c_adpt.h"
      16              : #include "hcomm_c_adpt_common.h"
      17              : #include "hcomm_res.h"
      18              : #include "hcomm_result_defs.h"
      19              : #include "hcomm_res_defs.h"
      20              : #include "hcomm_channel.h"
      21              : #include "log.h"
      22              : #include "param_check_pub.h"
      23              : #include "comm_engine_utils.h"
      24              : #include "channel_process.h"
      25              : #include "aicpu_ts_channel_helper.h"
      26              : #include "channel_config.h"
      27              : #include "shared_jetty_mgr.h"
      28              : #include "endpoint.h"
      29              : #include "builtin_endpoint_ops.h"
      30              : #include "nic_plugin_holder.h"
      31              : #include "nic_plugin_manager.h"
      32              : #include "acl/acl_rt.h"
      33              : #include "adapter_rts_common.h"
      34              : #include "tp_qos.h"
      35              : #include "hccl/hccl_types.h"
      36              : 
      37              : using namespace hcomm;
      38              : 
      39              : constexpr uint32_t kDscpToRoceTcShift = 2U; // RoCE TC = DSCP << 2(DiffServ 高 6 位为 DSCP)
      40              : 
      41            9 : static HcommResult ApplyRoceQosCompatToSlTc(HcommChannelDesc& channelDesc)
      42              : {
      43            9 :     if (channelDesc.qos == HCCL_COMM_QOS_CONFIG_NOT_SET) {
      44            3 :         return HCCL_SUCCESS;
      45              :     }
      46              : 
      47              :     // qos_dscp 仅 950/960 设备 HCCN 支持(按枚举精确匹配,避免代际数值比较误伤)
      48            6 :     DevType deviceType = DevType::DEV_TYPE_COUNT;
      49            6 :     CHK_RET(hrtGetDeviceType(deviceType));
      50            6 :     if (deviceType >= DevType::DEV_TYPE_COUNT) {
      51            1 :         HCCL_ERROR("[ApplyRoceQosCompatToSlTc] invalid deviceType[%d].", static_cast<int>(deviceType));
      52            1 :         return HCCL_E_PARA;
      53              :     }
      54            5 :     if (deviceType != DevType::DEV_TYPE_950 && deviceType != DevType::DEV_TYPE_960) {
      55            1 :         return HCCL_SUCCESS;
      56              :     }
      57              : 
      58            4 :     const uint8_t sl = static_cast<uint8_t>(channelDesc.qos & 0xFFU);
      59            4 :     uint8_t dscp = Hccl::kUboeDefaultDscp;
      60            4 :     s32 userDevId = 0;
      61            4 :     s32 phyDevId = 0;
      62            4 :     if (hrtGetDevice(&userDevId) != HCCL_SUCCESS || aclrtGetPhyDevIdByUserDevId(userDevId, &phyDevId) != ACL_SUCCESS) {
      63            0 :         HCCL_WARNING(
      64              :             "[ApplyRoceQosCompatToSlTc] get phyDevId failed, userDevId[%d], fallback to default dscp[%u].", userDevId,
      65              :             static_cast<unsigned>(dscp));
      66              :     } else {
      67            4 :         (void)Hccl::TpQosGetDscpByQosFromHccnCfg(static_cast<uint32_t>(phyDevId), sl, dscp);
      68              :     }
      69              : 
      70            4 :     channelDesc.roceAttr.sl = sl;
      71            4 :     channelDesc.roceAttr.tc = static_cast<uint8_t>((static_cast<uint32_t>(dscp) << kDscpToRoceTcShift) & 0xFFU);
      72            4 :     HCCL_INFO(
      73              :         "[ApplyRoceQosCompatToSlTc] qos compat: qos[%u] userDevId[%d] phyDevId[%d] dscp[%u] sl[%u] tc[%u].",
      74              :         channelDesc.qos, userDevId, phyDevId, static_cast<unsigned>(dscp),
      75              :         static_cast<unsigned>(channelDesc.roceAttr.sl), static_cast<unsigned>(channelDesc.roceAttr.tc));
      76            4 :     return HCCL_SUCCESS;
      77              : }
      78              : 
      79              : namespace {
      80            0 : void DestroyPluginCtx(HcommNicChannelOps* ops, void* pluginCtx)
      81              : {
      82            0 :     if (ops != nullptr && ops->destroy != nullptr) {
      83            0 :         int32_t ret = ops->destroy(pluginCtx);
      84            0 :         if (ret != HCCL_SUCCESS) {
      85            0 :             HCCL_WARNING("[%s] plugin channel destroy failed, ret[%d].", __func__, ret);
      86              :         }
      87              :     }
      88            0 : }
      89              : 
      90            0 : void RollbackPluginChannels(ChannelHandle* channels, uint32_t count)
      91              : {
      92            0 :     for (uint32_t i = 0; i < count; ++i) {
      93            0 :         if (channels[i] == 0)
      94            0 :             continue;
      95            0 :         auto* ch = CHANNEL_FROM_HANDLE(channels[i]);
      96            0 :         if (ch != nullptr) {
      97            0 :             HcclResult ret = ChannelProcess::RemovePluginChannelFromMap(reinterpret_cast<ChannelHandle>(ch));
      98            0 :             if (ret != HCCL_SUCCESS) {
      99            0 :                 HCCL_WARNING(
     100              :                     "[%s] plugin channel not found in map during rollback, handle[0x%llx], ret[%d].", __func__,
     101              :                     channels[i], ret);
     102              :             }
     103              :         }
     104            0 :         channels[i] = 0;
     105              :     }
     106            0 : }
     107              : 
     108            2 : HcommResult CreateOnePluginChannel(
     109              :     const NicPluginEntry* entry, void* epCtx, HcommChannelDesc* channelDesc, ChannelHandle* outChannel)
     110              : {
     111            2 :     *outChannel = 0;
     112              : 
     113            2 :     void* pluginCtx = nullptr;
     114            2 :     HcommNicChannelOps* pluginOps = nullptr;
     115            2 :     HcommResult ret = static_cast<HcommResult>(entry->createChannel(epCtx, channelDesc, &pluginCtx, &pluginOps));
     116            2 :     CHK_PRT_RET(
     117              :         (ret != HCCL_SUCCESS), HCCL_ERROR("[NicPlugin][%s] createChannel failed, ret[%d].", __func__, ret), ret);
     118              : 
     119            2 :     if (!ValidateChannelOps(pluginOps)) {
     120            0 :         HCCL_ERROR("[NicPlugin][%s] invalid channel ops.", __func__);
     121            0 :         DestroyPluginCtx(pluginOps, pluginCtx);
     122            0 :         return HCCL_E_INTERNAL;
     123              :     }
     124              : 
     125            2 :     HcommNicChannelOps* filledOps = nullptr;
     126            2 :     ret = FillDefaultChannelOps(pluginOps, &filledOps);
     127            2 :     if (ret != HCCL_SUCCESS) {
     128            0 :         HCCL_ERROR("[NicPlugin][%s] FillDefaultChannelOps failed, ret[%d].", __func__, ret);
     129            0 :         DestroyPluginCtx(pluginOps, pluginCtx);
     130            0 :         return ret;
     131              :     }
     132              : 
     133            2 :     ret = static_cast<HcommResult>(filledOps->init(pluginCtx));
     134            2 :     if (ret != HCCL_SUCCESS) {
     135            0 :         int32_t destroyRet = filledOps->destroy(pluginCtx);
     136            0 :         if (destroyRet != HCCL_SUCCESS) {
     137            0 :             HCCL_WARNING("[%s] plugin channel destroy failed after init failure, ret[%d].", __func__, destroyRet);
     138              :         }
     139            0 :         delete filledOps;
     140            0 :         HCCL_ERROR("[NicPlugin][%s] plugin channel init failed, ret[%d].", __func__, ret);
     141            0 :         return ret;
     142              :     }
     143              : 
     144            2 :     auto holder = std::make_shared<hcomm::PluginChannelHolder>(entry);
     145            2 :     holder->SetNicChannelCtx(filledOps, pluginCtx);
     146            2 :     ChannelHandle handle = reinterpret_cast<ChannelHandle>(holder.get());
     147              : 
     148            2 :     ret = static_cast<HcommResult>(ChannelProcess::InsertPluginChannelToMap(handle, std::move(holder)));
     149            2 :     CHK_PRT_RET(
     150              :         (ret != HCCL_SUCCESS), HCCL_ERROR("[NicPlugin][%s] InsertChannelToMap failed, ret[%d].", __func__, ret), ret);
     151              : 
     152            2 :     *outChannel = MAKE_PLUGIN_CH_HANDLE(handle);
     153            2 :     HCCL_INFO("[%s] plugin channel created, handle[0x%llx].", __func__, handle);
     154            2 :     return HCCL_SUCCESS;
     155            2 : }
     156              : 
     157              : } // namespace
     158              : 
     159           48 : HcommResult CheckUbAttr(HcommChannelDesc& channelDesc, [[maybe_unused]] CommEngine engine)
     160              : {
     161           48 :     if (channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UBC_TP
     162           47 :         && channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UBOE
     163           47 :         && channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UB_RTP
     164           47 :         && channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UB_CTP) {
     165           24 :         return HCCL_SUCCESS;
     166              :     }
     167              : 
     168              :     // 暂不支持UBOE场景下配置SqDepth
     169           24 :     if (channelDesc.remoteEndpoint.protocol == COMM_PROTOCOL_UBOE) {
     170            0 :         return HCCL_SUCCESS;
     171              :     }
     172              : 
     173              :     // check sqDepth
     174           24 :     if (channelDesc.ubAttr.sqDepth == UB_SQ_DEPTH_NOT_SET) {
     175           16 :         HCCL_INFO("[%s] use default ubAttr.sqDepth.", __func__);
     176           16 :         return HCCL_SUCCESS;
     177              :     }
     178              : 
     179              :     // channelDesc.ubAttr.sqDepth调整到2的整数次幂
     180            8 :     auto GetNextPowerOfTwo = [](uint32_t n) -> uint32_t {
     181            8 :         n--;
     182            8 :         n |= n >> 1;
     183            8 :         n |= n >> 2;
     184            8 :         n |= n >> 4;
     185            8 :         n |= n >> 8;
     186            8 :         n |= n >> 16;
     187            8 :         return n + 1;
     188              :     };
     189              : 
     190            8 :     channelDesc.ubAttr.sqDepth = GetNextPowerOfTwo(channelDesc.ubAttr.sqDepth);
     191              : 
     192            8 :     return HCCL_SUCCESS;
     193              : }
     194              : 
     195           47 : HcommResult CheckUbMemAttr(HcommChannelDesc& channelDesc)
     196              : {
     197           47 :     if (channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UB_MEM) {
     198           28 :         return HCOMM_SUCCESS;
     199              :     }
     200              : 
     201           19 :     if (channelDesc.ubMemAttr.pathMode == 0xFF) {
     202            1 :         HCCL_INFO("[%s] use default ubMemAttr.pathMode, set to 0.", __func__);
     203            1 :         channelDesc.ubMemAttr.pathMode = 0;
     204            1 :         return HCOMM_SUCCESS;
     205              :     }
     206              : 
     207           18 :     if (channelDesc.ubMemAttr.pathMode > 2) {
     208            3 :         HCCL_ERROR("[%s] invalid ubMemAttr.pathMode[%u], should be 0 ~ 2.", __func__, channelDesc.ubMemAttr.pathMode);
     209            3 :         return HCCL_E_PARA;
     210              :     }
     211           15 :     return HCOMM_SUCCESS;
     212              : }
     213              : 
     214           48 : HcommResult CheckRoceAttr(HcommChannelDesc& channelDesc)
     215              : {
     216           48 :     if (channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_ROCE) {
     217           39 :         return HCCL_SUCCESS;
     218              :     }
     219              : 
     220            9 :     if (channelDesc.roceAttr.queueNum == INVALID_UINT) {
     221            5 :         channelDesc.roceAttr.queueNum = 1;
     222            5 :         HCCL_INFO("[%s] set roceAttr.queueNum to 1.", __func__);
     223              :     }
     224              : 
     225            9 :     if (channelDesc.roceAttr.cqAttrFlags == INVALID_UINT) {
     226            9 :         channelDesc.roceAttr.cqAttrFlags = 0;
     227            9 :         HCCL_INFO("[%s] set roceAttr.cqAttrFlags to 0.", __func__);
     228              :     }
     229              : 
     230            9 :     return ApplyRoceQosCompatToSlTc(channelDesc);
     231              : }
     232              : 
     233              : namespace {
     234           40 : void ApplyHcommChannelDescV1Fields(const HcommChannelDesc& channelDesc, HcommChannelDesc& channelDescFinal)
     235              : {
     236           40 :     if (channelDesc.header.version < HCOMM_CHANNEL_VERSION_ONE) {
     237            0 :         return;
     238              :     }
     239              : 
     240           40 :     channelDescFinal.remoteEndpoint = channelDesc.remoteEndpoint;
     241           40 :     channelDescFinal.notifyNum = channelDesc.notifyNum;
     242           40 :     channelDescFinal.exchangeAllMems = channelDesc.exchangeAllMems;
     243           40 :     channelDescFinal.memHandles = channelDesc.memHandles;
     244           40 :     channelDescFinal.memHandleNum = channelDesc.memHandleNum;
     245           40 :     channelDescFinal.socket = channelDesc.socket;
     246           40 :     channelDescFinal.role = channelDesc.role;
     247           40 :     channelDescFinal.port = channelDesc.port;
     248              : }
     249              : 
     250           40 : HcommResult ProcessHcommChannelDescs(const HcommChannelDesc& channelDesc, HcommChannelDesc& channelDescFinal)
     251              : {
     252           40 :     if (channelDesc.header.size < sizeof(CommAbiHeader)) {
     253            0 :         HCCL_ERROR("[%s] invalid channelDesc.header.size[%u].", __func__, channelDesc.header.size);
     254            0 :         return HCCL_E_PARA;
     255              :     }
     256              : 
     257           40 :     if (channelDesc.header.magicWord != channelDescFinal.header.magicWord) {
     258            0 :         HCCL_ERROR(
     259              :             "[%s] channelDesc.header.magicWord[0x%08x] is invalid, expected[0x%08x].", __func__,
     260              :             channelDesc.header.magicWord, channelDescFinal.header.magicWord);
     261            0 :         return HCCL_E_PARA;
     262              :     }
     263              : 
     264           40 :     const uint32_t copySize = (channelDescFinal.header.size < channelDesc.header.size ? channelDescFinal.header.size :
     265           40 :                                                                                         channelDesc.header.size)
     266            0 :                               - sizeof(CommAbiHeader);
     267           40 :     CHK_SAFETY_FUNC_RET(memcpy_s(
     268              :         reinterpret_cast<uint8_t*>(&channelDescFinal) + sizeof(CommAbiHeader), copySize,
     269              :         reinterpret_cast<const uint8_t*>(&channelDesc) + sizeof(CommAbiHeader), copySize));
     270           40 :     ApplyHcommChannelDescV1Fields(channelDesc, channelDescFinal);
     271           40 :     if (channelDesc.header.version > HCOMM_CHANNEL_VERSION) {
     272            0 :         HCCL_RUN_WARNING(
     273              :             "The version of provided [%u] is higher than the current version[%u], "
     274              :             "unsupported configuration will be ignored.",
     275              :             channelDesc.header.version, HCOMM_CHANNEL_VERSION);
     276           40 :     } else if (channelDesc.header.version < HCOMM_CHANNEL_VERSION) {
     277            1 :         HCCL_RUN_WARNING(
     278              :             "The version of provided [%u] is lower than the current version[%u], "
     279              :             "configurations supported by later versions will be ignored.",
     280              :             channelDesc.header.version, HCOMM_CHANNEL_VERSION);
     281              :     }
     282              : 
     283              :     // qos:低版本时置默认值
     284           40 :     if (channelDesc.header.version <= HCOMM_CHANNEL_VERSION_ONE) {
     285            1 :         channelDescFinal.qos = 0xFFFFFFFFU;
     286              :     } else {
     287           39 :         channelDescFinal.qos = channelDesc.qos;
     288              :     }
     289              : 
     290              :     // v3:channelName,低版本时置 NULL
     291           40 :     constexpr uint32_t HCOMM_CHANNEL_VERSION_THREE = 3U;
     292           40 :     if (channelDesc.header.version < HCOMM_CHANNEL_VERSION_THREE) {
     293            1 :         channelDescFinal.channelName = nullptr;
     294              :     } else {
     295           39 :         channelDescFinal.channelName = channelDesc.channelName;
     296           39 :         if (channelDescFinal.channelName != nullptr
     297            1 :             && reinterpret_cast<uintptr_t>(channelDescFinal.channelName) == static_cast<uintptr_t>(-1)) {
     298            0 :             channelDescFinal.channelName = nullptr;
     299              :         }
     300              :     }
     301              : 
     302           40 :     if (channelDescFinal.channelName != nullptr) {
     303            1 :         size_t nameLen = strnlen(channelDescFinal.channelName, HCOMM_CHANNEL_NAME_MAX_LEN + 1);
     304            1 :         if (nameLen > HCOMM_CHANNEL_NAME_MAX_LEN) {
     305            0 :             HCCL_ERROR("[%s] channelName too long, max len[%u].", __func__, HCOMM_CHANNEL_NAME_MAX_LEN);
     306            0 :             return HCCL_E_PARA;
     307              :         }
     308              :     }
     309              : 
     310              :     // v4:roceAttr.srcPortList,低版本时 union 内该位置为脏数据,置 NULL
     311           40 :     if (channelDesc.header.version < HCOMM_CHANNEL_VERSION) {
     312            1 :         channelDescFinal.roceAttr.srcPortList = nullptr;
     313              :     } else {
     314           39 :         channelDescFinal.roceAttr.srcPortList = channelDesc.roceAttr.srcPortList;
     315              :     }
     316              : 
     317           40 :     return HCOMM_SUCCESS;
     318              : }
     319              : 
     320           40 : HcommResult NormalizeHcommChannelDescs(
     321              :     HcommChannelDesc* channelDescs, uint32_t channelNum, std::vector<HcommChannelDesc>& channelDescFinals,
     322              :     CommEngine engine)
     323              : {
     324           40 :     channelDescFinals.clear();
     325           40 :     channelDescFinals.reserve(channelNum);
     326           80 :     for (uint32_t idx = 0; idx < channelNum; ++idx) {
     327           40 :         HcommChannelDesc channelDescFinal{};
     328           40 :         HcommResult ret = HcommChannelDescInit(&channelDescFinal, 1);
     329           40 :         if (ret != HCOMM_SUCCESS) {
     330            0 :             return ret;
     331              :         }
     332           40 :         ret = ProcessHcommChannelDescs(channelDescs[idx], channelDescFinal);
     333           40 :         if (ret != HCOMM_SUCCESS) {
     334            0 :             HCCL_ERROR("[%s] failed to normalize channelDesc[%u], ret[%d].", __func__, idx, ret);
     335            0 :             return ret;
     336              :         }
     337           40 :         ret = CheckUbAttr(channelDescFinal, engine);
     338           40 :         if (ret != HCOMM_SUCCESS) {
     339            0 :             HCCL_ERROR("[%s] CheckUbAttr failed, ret[%d].", __func__, ret);
     340            0 :             return ret;
     341              :         }
     342           40 :         ret = CheckUbMemAttr(channelDescFinal);
     343           40 :         if (ret != HCOMM_SUCCESS) {
     344            0 :             HCCL_ERROR("[%s] CheckUbMemAttr failed, ret[%d].", __func__, ret);
     345            0 :             return ret;
     346              :         }
     347           40 :         ret = CheckRoceAttr(channelDescFinal);
     348           40 :         if (ret != HCOMM_SUCCESS) {
     349            0 :             HCCL_ERROR("[%s] CheckRoceAttr failed, ret[%d].", __func__, ret);
     350            0 :             return ret;
     351              :         }
     352              : 
     353           40 :         channelDescFinals.push_back(channelDescFinal);
     354              :     }
     355           40 :     return HCOMM_SUCCESS;
     356              : }
     357              : } // namespace
     358              : 
     359              : // 集合通信使用,待归一到HcommChannelCreate
     360           22 : HcommResult HcommCollectiveChannelCreate(
     361              :     EndpointHandle endpointHandle, CommEngine engine, HcommChannelDesc* channelDescs, uint32_t channelNum,
     362              :     ChannelHandle* channels)
     363              : {
     364           22 :     CHK_PTR_NULL(channelDescs);
     365           20 :     CHK_PTR_NULL(channels);
     366           20 :     CHK_PRT_RET(
     367              :         (channelNum == 0), HCCL_ERROR("[%s] Invalid channelNum, channelNum[%u]", __func__, channelNum), HCCL_E_PARA);
     368           18 :     std::vector<HcommChannelDesc> channelDescFinals;
     369           18 :     CHK_RET(static_cast<HcclResult>(NormalizeHcommChannelDescs(channelDescs, channelNum, channelDescFinals, engine)));
     370           18 :     auto startut = std::chrono::steady_clock::now();
     371           18 :     HCCL_INFO(
     372              :         "[%s] START. endpointHandle[0x%llx], engine[%s], channelNum[%u].", __func__, endpointHandle,
     373              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), channelNum);
     374              :     HcommResult ret
     375           18 :         = ChannelProcess::CreateChannelsLoop(endpointHandle, engine, channelDescFinals.data(), channelNum, channels);
     376           18 :     HCCL_INFO(
     377              :         "[%s] END. channelNum[%u], take time [%lld]us.", __func__, channelNum,
     378              :         std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - startut).count());
     379           18 :     return ret;
     380           18 : }
     381              : 
     382            0 : HcommResult HcommChannelUpdateMemInfo(HcommMemHandle* memHandles, uint32_t memHandleNum, ChannelHandle channelHandle)
     383              : {
     384            0 :     CHK_PTR_NULL(memHandles);
     385            0 :     CHK_PRT_RET(
     386              :         (memHandleNum == 0), HCCL_ERROR("[%s] Invalid memHandleNum, memHandleNum is 0.", __func__), HCCL_E_PARA);
     387            0 :     return ChannelProcess::ChannelUpdateMemInfo(memHandles, memHandleNum, channelHandle);
     388              : }
     389              : 
     390            2 : HcommResult CreatePluginChannels(
     391              :     hcomm::Endpoint* endpoint, HcommChannelDesc* channelDescs, uint32_t channelNum, ChannelHandle* channels)
     392              : {
     393            2 :     auto* epHolder = dynamic_cast<hcomm::PluginEndpointHolder*>(endpoint);
     394            2 :     CHK_PTR_NULL(epHolder);
     395            2 :     const NicPluginEntry* entry = epHolder->GetPluginEntry();
     396            2 :     CHK_PTR_NULL(entry);
     397            2 :     void* epCtx = endpoint->GetNicCtx();
     398              : 
     399            4 :     for (uint32_t idx = 0; idx < channelNum; ++idx) {
     400            2 :         HcommResult ret = CreateOnePluginChannel(entry, epCtx, &channelDescs[idx], &channels[idx]);
     401            2 :         if (ret != HCCL_SUCCESS) {
     402            0 :             (void)RollbackPluginChannels(channels, idx);
     403            0 :             return ret;
     404              :         }
     405              :     }
     406              : 
     407            2 :     return HCCL_SUCCESS;
     408              : }
     409              : 
     410           27 : HcommResult HcommChannelCreate(
     411              :     EndpointHandle endpointHandle, CommEngine engine, HcommChannelDesc* channelDescs, uint32_t channelNum,
     412              :     ChannelHandle* channels)
     413              : {
     414           27 :     CHK_PTR_NULL(endpointHandle);
     415           24 :     CHK_PTR_NULL(channelDescs);
     416           23 :     CHK_PTR_NULL(channels);
     417           23 :     CHK_PRT_RET(
     418              :         (channelNum == 0), HCCL_ERROR("[%s] Invalid channelNum, channelNum[%u]", __func__, channelNum), HCCL_E_PARA);
     419           22 :     std::vector<HcommChannelDesc> channelDescFinals;
     420           22 :     CHK_RET(static_cast<HcclResult>(NormalizeHcommChannelDescs(channelDescs, channelNum, channelDescFinals, engine)));
     421           22 :     auto endpoint = GetEndpointMap().GetEndpoint(endpointHandle);
     422           22 :     auto startut = std::chrono::steady_clock::now();
     423           22 :     HCCL_INFO(
     424              :         "[%s] START. endpointHandle[0x%llx], engine[%s], channelNum[%u].", __func__, endpointHandle,
     425              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), channelNum);
     426           22 :     if (endpoint != nullptr && endpoint->GetNicOps() != nullptr && endpoint->GetNicOps() != &g_BuiltinEndpointOps) {
     427            2 :         CHK_RET(
     428              :             static_cast<HcclResult>(CreatePluginChannels(endpoint, channelDescFinals.data(), channelNum, channels)));
     429            2 :         HCCL_INFO(
     430              :             "[%s] END. channelNum[%u], take time [%lld]us.", __func__, channelNum,
     431              :             std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - startut).count());
     432            2 :         return HCCL_SUCCESS;
     433              :     }
     434           20 :     (void)HcommResMgrInit();
     435           20 :     if (endpoint != nullptr) {
     436           18 :         CHK_RET(RefreshEndpointContext(endpoint->GetEndpointDesc()));
     437              :     }
     438           20 :     std::vector<ChannelHandle> hostChannelHandles(channelNum);
     439           20 :     ChannelHandle* targetChannels = hostChannelHandles.data();
     440           20 :     CHK_RET(ChannelProcess::CreateChannelsLoop(
     441              :         endpointHandle, engine, channelDescFinals.data(), channelNum, targetChannels));
     442           20 :     CHK_RET(
     443              :         ChannelProcess::PrepareUserChannels(targetChannels, channels, channelDescFinals.data(), channelNum, engine));
     444           19 :     HCCL_INFO(
     445              :         "[%s] END. channelNum[%u], take time [%lld]us.", __func__, channelNum,
     446              :         std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - startut).count());
     447           19 :     HCCL_RUN_INFO(
     448              :         "[%s] channels created, channelNum[%u], engine[%s]", __func__, channelNum,
     449              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str());
     450           19 :     return HCCL_SUCCESS;
     451           22 : }
     452              : 
     453           59 : HcommResult HcommChannelGet(ChannelHandle channelHandle, void** channel)
     454              : {
     455           59 :     CHK_PTR_NULL(channel);
     456           58 :     return ChannelProcess::ChannelGet(channelHandle, channel);
     457              : }
     458              : 
     459           36 : HcommResult HcommChannelGetStatus(const ChannelHandle* channelList, uint32_t listNum, int32_t* statusList)
     460              : {
     461           36 :     CHK_PTR_NULL(channelList);
     462           34 :     CHK_PTR_NULL(statusList);
     463           32 :     CHK_PRT_RET((listNum == 0), HCCL_ERROR("[%s] Invalid listNum, listNum[%u]", __func__, listNum), HCCL_E_PARA);
     464              : 
     465           30 :     if (IS_PLUGIN_HANDLE(channelList[0])) {
     466            3 :         for (uint32_t i = 0; i < listNum; i++) {
     467            2 :             auto* ch = CHANNEL_FROM_HANDLE(channelList[i]);
     468            3 :             CHK_PTR_NULL(ch);
     469            2 :             int32_t status = 0;
     470            2 :             HcommResult ret = static_cast<HcommResult>(ch->GetNicOps()->getStatus(ch->GetNicCtx(), &status));
     471            2 :             if (ret != HCCL_SUCCESS) {
     472            1 :                 HCCL_ERROR("[%s] plugin getStatus failed, idx[%u], ret[%d].", __func__, i, ret);
     473            1 :                 return ret;
     474              :             }
     475            1 :             statusList[i] = status;
     476              :         }
     477            1 :         return HCCL_SUCCESS;
     478              :     } else {
     479           28 :         (void)HcommResMgrInit();
     480           28 :         std::vector<CommEngine> engines;
     481           28 :         std::vector<HcommChannelDesc> channelDescFinals;
     482           28 :         std::vector<ChannelStatus> internalStatus(listNum);
     483           28 :         auto startut = std::chrono::steady_clock::now();
     484              :         HcclResult ret
     485           28 :             = ChannelProcess::GetChannelsInfo(channelList, listNum, engines, channelDescFinals, internalStatus);
     486           28 :         if (ret != HCCL_SUCCESS) {
     487            2 :             HCCL_ERROR("[%s] GetChannelsInfo failed, ret[%d]", __func__, ret);
     488            2 :             return HCCL_E_INTERNAL;
     489              :         }
     490           26 :         ret = ChannelProcess::HandleStatusByEngine(
     491              :             channelList, listNum, engines, channelDescFinals, internalStatus, statusList);
     492           26 :         if (ret != HCCL_SUCCESS) {
     493            0 :             HCCL_ERROR("[%s] HandleStatusByEngine failed, ret[%d]", __func__, ret);
     494            0 :             return HCCL_E_INTERNAL;
     495              :         }
     496           26 :         HCCL_INFO(
     497              :             "[%s] END. listNum[%u], take time [%lld]us.", __func__, listNum,
     498              :             std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - startut).count());
     499           26 :         return HCCL_SUCCESS;
     500           28 :     }
     501              : }
     502              : 
     503            2 : HcommResult HcommChannelGetNotifyNum(ChannelHandle channelHandle, uint32_t* notifyNum)
     504              : {
     505            2 :     CHK_PTR_NULL(notifyNum);
     506            1 :     return ChannelProcess::ChannelGetNotifyNum(channelHandle, notifyNum);
     507              : }
     508              : 
     509           19 : static HcclResult DestroyBuiltinChannels(std::vector<ChannelHandle>& builtinChannels)
     510              : {
     511              :     // 即使 plugin channel 销毁失败,也需继续销毁 builtin channel,避免 RDMA/jetty 资源泄漏
     512              :     // 及 SharedJettyMgr 残留记录永久阻塞 Endpoint 销毁。最终返回首个错误(优先 plugin 错误)。
     513           19 :     HcclResult builtinRet = HCCL_SUCCESS;
     514           19 :     if (builtinChannels.empty()) {
     515            0 :         return builtinRet;
     516              :     }
     517           38 :     builtinRet = ChannelProcess::ChannelDestroy(
     518           19 :         builtinChannels.data(), builtinChannels.size(), AicpuTsChannelHelper::GetBinHandle());
     519              :     // 无论 ChannelDestroy 成功与否都注销 SharedJettyMgr 记录:
     520              :     // 成功时正常清理;失败时 channel 已不可用,若不注销会永久阻塞 Endpoint 销毁。
     521           19 :     if (builtinRet != HCCL_SUCCESS) {
     522            0 :         HCCL_WARNING(
     523              :             "[%s] ChannelDestroy failed, ret[%d], force unregister shared jetty channels.", __func__, builtinRet);
     524              :     }
     525           19 :     (void)hcomm::SharedJettyMgr::GetInstance().UnregisterChannels(builtinChannels.data(), builtinChannels.size());
     526           19 :     return builtinRet;
     527              : }
     528              : 
     529           23 : HcommResult HcommChannelDestroy(const ChannelHandle* channels, uint32_t channelNum)
     530              : {
     531           23 :     CHK_PTR_NULL(channels);
     532           22 :     CHK_PRT_RET(
     533              :         (channelNum == 0), HCCL_ERROR("[%s] Invalid channelNum, channelNum[%u]", __func__, channelNum), HCCL_E_PARA);
     534           21 :     if (IS_PLUGIN_HANDLE(channels[0])) {
     535            4 :         for (uint32_t idx = 0; idx < channelNum; ++idx) {
     536            2 :             auto* ch = CHANNEL_FROM_HANDLE(channels[idx]);
     537            2 :             HcclResult ret = ChannelProcess::RemovePluginChannelFromMap(reinterpret_cast<ChannelHandle>(ch));
     538            2 :             if (ret != HCCL_SUCCESS) {
     539            0 :                 HCCL_WARNING(
     540              :                     "[%s] plugin channel not found in map during destroy, handle[0x%llx], ret[%d].", __func__,
     541              :                     channels[idx], ret);
     542              :             }
     543              :         }
     544            2 :         return HCCL_SUCCESS;
     545              :     }
     546           19 :     (void)HcommResMgrInit();
     547           19 :     std::vector<ChannelHandle> builtinChannels;
     548           19 :     builtinChannels.reserve(channelNum);
     549           39 :     for (uint32_t idx = 0; idx < channelNum; ++idx) {
     550           20 :         builtinChannels.push_back(channels[idx]);
     551              :     }
     552           19 :     return static_cast<HcommResult>(DestroyBuiltinChannels(builtinChannels));
     553           19 : }
     554              : 
     555            5 : HcommResult HcommChannelConfigCreate(HcommChannelConfig* config)
     556              : {
     557            5 :     return static_cast<HcommResult>(hcomm::ChannelConfigCreate(config));
     558              : }
     559              : 
     560            5 : HcommResult HcommChannelConfigDestroy(HcommChannelConfig config)
     561              : {
     562            5 :     return static_cast<HcommResult>(hcomm::ChannelConfigDestroy(config));
     563              : }
     564              : 
     565            3 : HcommResult HcommChannelConfigSetInt(HcommChannelConfig config, HcommChannelConfigType type, uint32_t value)
     566              : {
     567            3 :     return static_cast<HcommResult>(hcomm::ChannelConfigSetInt(config, type, value));
     568              : }
     569              : 
     570            0 : static bool IsUbProtocol(CommProtocol protocol)
     571              : {
     572            0 :     return protocol == COMM_PROTOCOL_UB_CTP || protocol == COMM_PROTOCOL_UBC_TP;
     573              : }
     574              : 
     575            0 : static HcclResult ValidateSharedQueueConfig(const std::vector<HcommChannelDesc>& channelDescs)
     576              : {
     577            0 :     for (uint32_t i = 0; i < channelDescs.size(); ++i) {
     578            0 :         CommProtocol protocol = channelDescs[i].remoteEndpoint.protocol;
     579            0 :         if (!IsUbProtocol(protocol)) {
     580            0 :             HCCL_ERROR(
     581              :                 "[%s] IS_SHARED_QUEUE only supports UB protocols (UB_CTP/UBC_TP), "
     582              :                 "channelDesc[%u] protocol[%d].",
     583              :                 __func__, i, protocol);
     584            0 :             return HCCL_E_NOT_SUPPORT;
     585              :         }
     586              :     }
     587            0 :     return HCCL_SUCCESS;
     588              : }
     589              : 
     590            0 : static HcclResult CreateAndRegisterSharedQueueBuiltinChannels(
     591              :     EndpointHandle endpointHandle, CommEngine engine, HcommChannelDesc* channelDescFinals, uint32_t channelNum,
     592              :     ChannelHandle* channels)
     593              : {
     594              :     // 共享模式建链流程与 HcommChannelCreate 一致:CreateChannelsLoop 传 isSharedQueue=true,
     595              :     // channel 的 BuildConnection 据此走共享 jetty 复用路径;PrepareUserChannels 完成 AICPU/AIV 预分配。
     596            0 :     std::vector<ChannelHandle> hostChannelHandles(channelNum);
     597            0 :     ChannelHandle* targetChannels = hostChannelHandles.data();
     598              : 
     599            0 :     CHK_RET(ChannelProcess::CreateChannelsLoop(
     600              :         endpointHandle, engine, channelDescFinals, channelNum, targetChannels, true));
     601              :     HcclResult prepRet
     602            0 :         = ChannelProcess::PrepareUserChannels(targetChannels, channels, channelDescFinals, channelNum, engine);
     603            0 :     if (prepRet != HCCL_SUCCESS) {
     604            0 :         HCCL_ERROR("[%s] PrepareUserChannels failed, ret[%d], destroying created channels.", __func__, prepRet);
     605            0 :         (void)ChannelProcess::ChannelDestroy(targetChannels, channelNum, AicpuTsChannelHelper::GetBinHandle());
     606            0 :         return prepRet;
     607              :     }
     608              : 
     609            0 :     HcclResult regRet = hcomm::SharedJettyMgr::GetInstance().RegisterChannels(endpointHandle, channels, channelNum);
     610            0 :     if (regRet != HCCL_SUCCESS) {
     611            0 :         HCCL_ERROR("[%s] failed to register shared jetty channels, ret[%d].", __func__, regRet);
     612            0 :         (void)ChannelProcess::ChannelDestroy(channels, channelNum, AicpuTsChannelHelper::GetBinHandle());
     613            0 :         return regRet;
     614              :     }
     615            0 :     return HCCL_SUCCESS;
     616            0 : }
     617              : 
     618            0 : HcommResult HcommChannelCreateWithConfig(
     619              :     EndpointHandle endpointHandle, CommEngine engine, HcommChannelDesc* channelDescs, uint32_t channelNum,
     620              :     HcommChannelConfig config, ChannelHandle* channels)
     621              : {
     622            0 :     CHK_PTR_NULL(endpointHandle);
     623            0 :     CHK_PTR_NULL(channelDescs);
     624            0 :     CHK_PTR_NULL(channels);
     625            0 :     CHK_PRT_RET(
     626              :         (channelNum == 0), HCCL_ERROR("[%s] Invalid channelNum, channelNum[%u]", __func__, channelNum), HCCL_E_PARA);
     627            0 :     HCCL_INFO(
     628              :         "[%s] START. endpointHandle[0x%llx], engine[%s], channelNum[%u], config[%p].", __func__, endpointHandle,
     629              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), channelNum, config);
     630              : 
     631            0 :     bool isSharedQueue = false;
     632            0 :     if (config != nullptr) {
     633            0 :         auto* cfg = static_cast<hcomm::HcommChannelConfigData*>(config);
     634            0 :         isSharedQueue = cfg->isSharedQueue;
     635              :     }
     636              : 
     637              :     // 非共享模式直接复用 HcommChannelCreate 流程,避免重复维护两套建链逻辑
     638            0 :     if (!isSharedQueue) {
     639            0 :         return HcommChannelCreate(endpointHandle, engine, channelDescs, channelNum, channels);
     640              :     }
     641              : 
     642              :     // 共享 jetty 仅支持 AIV 引擎:AICPU 等 channel 的 BuildConnection 不处理共享 jetty 路径,
     643              :     // 强行创建会导致 channel 注册到 SharedJettyMgr 但无实际 jetty 共享,多 channel 共用同一 SQ
     644              :     // 但 PI/CI 未协调,引发 WQE 覆盖、doorbell 不前进、notify 超时。
     645            0 :     if (engine != COMM_ENGINE_AIV) {
     646            0 :         HCCL_ERROR(
     647              :             "[%s] IS_SHARED_QUEUE currently only supports AIV engine, engine[%d].", __func__, static_cast<int>(engine));
     648            0 :         return HCCL_E_NOT_SUPPORT;
     649              :     }
     650              : 
     651            0 :     auto endpoint = GetEndpointMap().GetEndpoint(endpointHandle);
     652            0 :     if (endpoint != nullptr) {
     653            0 :         CHK_RET(RefreshEndpointContext(endpoint->GetEndpointDesc()));
     654              :     }
     655            0 :     (void)HcommResMgrInit();
     656              : 
     657            0 :     std::vector<HcommChannelDesc> channelDescFinals;
     658            0 :     CHK_RET(static_cast<HcclResult>(NormalizeHcommChannelDescs(channelDescs, channelNum, channelDescFinals, engine)));
     659              :     // NormalizeHcommChannelDescs 内部已调 CheckUbAttr,此处仅补共享模式专有校验
     660            0 :     CHK_RET(ValidateSharedQueueConfig(channelDescFinals));
     661              : 
     662            0 :     HcclResult ret = CreateAndRegisterSharedQueueBuiltinChannels(
     663              :         endpointHandle, engine, channelDescFinals.data(), channelNum, channels);
     664            0 :     if (ret != HCCL_SUCCESS) {
     665            0 :         return static_cast<HcommResult>(ret);
     666              :     }
     667              : 
     668            0 :     HCCL_INFO("[%s] SUCCESS. isSharedQueue[%d], channelNum[%u].", __func__, isSharedQueue, channelNum);
     669            0 :     return HCCL_SUCCESS;
     670            0 : }
     671              : 
     672              : HcommResult
     673            7 : HcommChannelGetRemoteMems(ChannelHandle channelHandle, uint32_t* memNum, CommMem** remoteMem, char*** memInfos)
     674              : {
     675            7 :     CHK_PTR_NULL(remoteMem);
     676            6 :     CHK_PTR_NULL(memNum);
     677            5 :     CHK_PTR_NULL(memInfos);
     678              : 
     679            5 :     return ChannelProcess::ChannelGetRemoteMems(channelHandle, memNum, remoteMem, memInfos);
     680              : }
        

Generated by: LCOV version 2.0-1