LCOV - code coverage report
Current view: top level - legacy/ascend950/framework/env_config - env_func.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 66.1 % 581 384
Test Date: 2026-08-18 17:47:01 Functions: 90.7 % 43 39

            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 "env_func.h"
      12              : #include <climits>
      13              : #include <fstream>
      14              : #include <linux/limits.h>
      15              : #include <cctype>
      16              : #include <algorithm>
      17              : #include <sstream>
      18              : #include <array>
      19              : 
      20              : #include "sal.h"
      21              : #include "string_util.h"
      22              : #include "base_config.h"
      23              : #include "orion_adapter_rts.h"
      24              : #include "adapter_error_manager_pub.h"
      25              : 
      26              : namespace Hccl {
      27              : 
      28              : /*----------------------------- cast functions -------------------------*/
      29              : 
      30           10 : bool CastBin2Bool(const std::string& s)
      31              : {
      32           10 :     bool b = true;
      33           10 :     if (s == "0") {
      34            3 :         b = false;
      35            7 :     } else if (s == "1") {
      36            3 :         b = true;
      37              :     } else {
      38            4 :         THROW<InvalidParamsException>(StringFormat("Env config \"%s\" is not valid. Should be 0 or 1", s.c_str()));
      39              :     }
      40            6 :     return b;
      41              : }
      42              : 
      43            2 : u32 CastBin2UInt(const std::string& s)
      44              : {
      45            2 :     u32 b = std::stoi(s);
      46            2 :     if (b > HCCL_CCU_FLAG_NUM) {
      47            2 :         THROW<InvalidParamsException>(StringFormat("Env config \"%s\" is not valid. Should be 0 or 1 or 2", s.c_str()));
      48              :     }
      49            3 :     HCCL_INFO("[CastBin2UInt] string[%s] to u32[%u]", s.c_str(), b);
      50            1 :     return b;
      51              : }
      52              : 
      53            2 : static HcclResult SplitHcclSocketIfName(const std::string& socketIfName, std::vector<std::string>& configIfNames)
      54              : {
      55            2 :     std::size_t start = 0;
      56            2 :     std::size_t end = socketIfName.find(",");
      57            4 :     while (end != std::string::npos) {
      58            2 :         if (start == 0 && end == 0) {
      59            0 :             HCCL_ERROR("[Split][HcclSocketIfName] configIfNames config is invalid.");
      60            0 :             return HCCL_E_PARA;
      61              :         }
      62            2 :         configIfNames.push_back(socketIfName.substr(start, end - start));
      63            2 :         start = end + 1;
      64            2 :         end = socketIfName.find(",", start);
      65              :     }
      66              :     // 处理最后一个部分
      67            2 :     if (start < socketIfName.length()) {
      68            2 :         configIfNames.push_back(socketIfName.substr(start));
      69            0 :     } else if (start == 0) {
      70            0 :         HCCL_ERROR("[Split][HcclSocketIfName] configIfNames config is invalid.");
      71            0 :         return HCCL_E_PARA;
      72              :     }
      73            2 :     return HCCL_SUCCESS;
      74              : }
      75              : 
      76              : // 临时方案,且当前未使用,测试期望在此拦截该环境变量所有异常值
      77            2 : SocketIfName CastSocketIfName(const std::string& s)
      78              : {
      79            2 :     SocketIfName hcclSocketIfNameGroup{};
      80            2 :     hcclSocketIfNameGroup.configIfNameStr = s;
      81            2 :     std::string hcclSocketIfName = s;
      82            2 :     std::string remainSocketIfName = hcclSocketIfName;
      83            2 :     bool searchNot = false;
      84            2 :     bool searchExact = false;
      85              : 
      86            2 :     if (hcclSocketIfName.length() != 0) {
      87              :         // 获取HCCL_SOCKET_IFNAME环境变量匹配规则
      88            2 :         if (!hcclSocketIfName.empty() && hcclSocketIfName.at(0) == '^') {
      89            1 :             searchNot = true;
      90              :             // 获取从1位置开始剩余部分环境变量内容
      91            1 :             remainSocketIfName = hcclSocketIfName.substr(1);
      92              :         }
      93              : 
      94            2 :         if (!remainSocketIfName.empty() && remainSocketIfName.at(0) == '=') {
      95            2 :             searchExact = true;
      96            2 :             remainSocketIfName = remainSocketIfName.substr(1);
      97              :         }
      98              : 
      99              :         // 获取用户输入的网卡名列表(使用逗号隔开),将网卡名列表存放到vector变量中
     100            2 :         HcclResult ret = SplitHcclSocketIfName(remainSocketIfName, hcclSocketIfNameGroup.configIfNames);
     101            2 :         if (ret != HCCL_SUCCESS) {
     102            0 :             THROW<InvalidParamsException>(StringFormat(
     103              :                 "environmental variable HCCL_SOCKET_IFNAME[%s] is invalid. "
     104              :                 "please check.",
     105              :                 s.c_str()));
     106              :         }
     107            6 :         HCCL_INFO("HCCL_SOCKET_IFNAME set by environment to [%s]", hcclSocketIfName.c_str());
     108              :     } else {
     109            0 :         HCCL_INFO("HCCL_SOCKET_IFNAME set by default to [%s]", hcclSocketIfName.c_str());
     110              :     }
     111            2 :     hcclSocketIfNameGroup.searchNot = searchNot;
     112            2 :     hcclSocketIfNameGroup.searchExact = searchExact;
     113            2 :     return hcclSocketIfNameGroup;
     114            2 : }
     115              : 
     116           36 : bool SplitString(std::string& totalStr, std::string& prefixStr, const std::string& delim)
     117              : {
     118           36 :     std::size_t found = totalStr.find(delim);
     119           36 :     if (found == std::string::npos) {
     120           14 :         return false;
     121              :     }
     122           22 :     prefixStr = totalStr.substr(0, found);
     123           22 :     totalStr = totalStr.substr(found + 1);
     124           22 :     return true;
     125              : }
     126              : 
     127           30 : void GetUIntFromStr(const std::string& digitStr, u32& val)
     128              : {
     129           30 :     bool isAllDigits = std::all_of(digitStr.begin(), digitStr.end(), ::isdigit);
     130           30 :     CHK_PRT_THROW(
     131              :         !isAllDigits, HCCL_ERROR("[GetUIntFromStr] str[%s] is not all digit.", digitStr.c_str()),
     132              :         InvalidParamsException, "parser portRange fail.");
     133           30 :     auto ret = SalStrToULong(digitStr.c_str(), HCCL_BASE_DECIMAL, val);
     134           30 :     CHK_PRT_THROW(
     135              :         ret != HCCL_SUCCESS, HCCL_ERROR("[GetUIntFromStr] str[%s] is a invalid number.", digitStr.c_str()),
     136              :         InvalidParamsException, "parser portRange fail.");
     137           30 : }
     138              : 
     139           18 : void SplitSinglePortRange(const std::string& envName, std::string& rangeStr, SocketPortRange& portRange)
     140              : {
     141           18 :     std::string rangeMin{};
     142           18 :     const std::string delim = "-";
     143           18 :     if (SplitString(rangeStr, rangeMin, delim)) {
     144           12 :         GetUIntFromStr(rangeMin, portRange.min);
     145           12 :         GetUIntFromStr(rangeStr, portRange.max);
     146              :     } else {
     147            6 :         GetUIntFromStr(rangeStr, portRange.min);
     148            6 :         portRange.max = portRange.min;
     149              :     }
     150           52 :     HCCL_INFO(
     151              :         "[SplitSinglePortRange] Load hccl socket port range [%u, %u] from %s", portRange.min, portRange.max,
     152              :         envName.c_str());
     153           18 : }
     154              : 
     155            8 : void CheckSocketPortRangeValid(const std::string& envName, const std::vector<SocketPortRange>& portRanges)
     156              : {
     157            8 :     std::vector<SocketPortRange> rangeVec(portRanges.begin(), portRanges.end());
     158            8 :     std::sort(rangeVec.begin(), rangeVec.end(), [](SocketPortRange& a, SocketPortRange& b) {
     159           18 :         return (a.min == b.min) ? (a.max < b.max) : (a.min < b.min);
     160              :     });
     161           16 :     for (size_t i = 0; i < rangeVec.size(); ++i) {
     162              :         // the socket range should not be inverted
     163           18 :         CHK_PRT_THROW(
     164              :             rangeVec[i].min > rangeVec[i].max,
     165              :             HCCL_ERROR(
     166              :                 "[%s] In %s, in socket port range [%u, %u], the lower bound is greater than"
     167              :                 " the upper bound.",
     168              :                 __func__, envName.c_str(), rangeVec[i].min, rangeVec[i].max),
     169              :             InvalidParamsException, "check portRange fail.");
     170              : 
     171              :         // the socket range should not include the reserved port for auto listening.
     172           22 :         CHK_PRT_THROW(
     173              :             (rangeVec[i].min <= HCCL_SOCKET_PORT_RANGE_AUTO),
     174              :             HCCL_ERROR(
     175              :                 "[%s] In %s, socket port range [%u, %u] includes the reserved port number [%u]. "
     176              :                 "please do not use port [%u] in socket port range.",
     177              :                 __func__, envName.c_str(), rangeVec[i].min, rangeVec[i].max, HCCL_SOCKET_PORT_RANGE_AUTO,
     178              :                 HCCL_SOCKET_PORT_RANGE_AUTO),
     179              :             InvalidParamsException, "check portRange fail.");
     180              : 
     181              :         // the socket range should not exceed the maximum port number
     182           15 :         CHK_PRT_THROW(
     183              :             rangeVec[i].max > MAX_PORT_NUMBER,
     184              :             HCCL_ERROR(
     185              :                 "[%s] In %s, in socket port range [%u, %u], the upper bound exceed max port number[%u].", __func__,
     186              :                 envName.c_str(), rangeVec[i].min, rangeVec[i].max, MAX_PORT_NUMBER),
     187              :             InvalidParamsException, "check portRange fail.");
     188              : 
     189              :         // the socket range should not be overlapped
     190           14 :         CHK_PRT_THROW(
     191              :             i != 0 && rangeVec[i - 1].max >= rangeVec[i].min,
     192              :             HCCL_ERROR(
     193              :                 "[%s] In %s, socket port range [%u, %u] is conflict with socket port range [%u, %u].", __func__,
     194              :                 envName.c_str(), rangeVec[i - 1].min, rangeVec[i - 1].max, rangeVec[i].min, rangeVec[i].max),
     195              :             InvalidParamsException, "check portRange fail.");
     196              :     }
     197            8 : }
     198              : 
     199            8 : void SplitHcclSocketPortRange(
     200              :     const std::string& envName, std::string& portRangeConfig, std::vector<SocketPortRange>& portRangeVec)
     201              : {
     202            8 :     std::string rangeStr{};
     203            8 :     const std::string delim = ",";
     204           18 :     while (SplitString(portRangeConfig, rangeStr, delim)) {
     205           10 :         SocketPortRange portRange = {};
     206           10 :         SplitSinglePortRange(envName, rangeStr, portRange);
     207           10 :         portRangeVec.emplace_back(portRange);
     208              :     }
     209            8 :     SocketPortRange portRange = {};
     210            8 :     SplitSinglePortRange(envName, portRangeConfig, portRange);
     211            8 :     portRangeVec.emplace_back(portRange);
     212              : 
     213            8 :     CheckSocketPortRangeValid(envName, portRangeVec);
     214           13 : }
     215              : 
     216            3 : void PrintSocketPortRange(const std::string& envName, const std::vector<SocketPortRange>& portRangeVec)
     217              : {
     218              :     // assemble port ranges into a string to print the result range
     219            3 :     std::ostringstream portRangeOss;
     220            8 :     for (auto range : portRangeVec) {
     221            5 :         portRangeOss << " [" << std::to_string(range.min) << ", " << std::to_string(range.max) << "]";
     222              :     }
     223            7 :     HCCL_INFO("%s is set to%s.", envName.c_str(), portRangeOss.str().c_str());
     224            3 : }
     225              : 
     226            9 : std::vector<SocketPortRange> CastSocketPortRange(const std::string& s, const std::string& envName)
     227              : {
     228            9 :     std::vector<SocketPortRange> hcclSocketPortRange;
     229              :     // the environment variable is not set
     230            9 :     std::string socketPortRange = s;
     231            9 :     if (socketPortRange.length() == 0) {
     232            0 :         return hcclSocketPortRange;
     233              :     }
     234              : 
     235              :     // the socket port range is set to auto, then the os will listen on the ports dymamically and automatically.
     236            9 :     if (socketPortRange == HCCL_AUTO_PORT_CONFIG) {
     237            1 :         SocketPortRange autoSocketPortRange = {HCCL_SOCKET_PORT_RANGE_AUTO, HCCL_SOCKET_PORT_RANGE_AUTO};
     238            1 :         hcclSocketPortRange.emplace_back(autoSocketPortRange);
     239              : 
     240            3 :         HCCL_INFO(
     241              :             "HCCL_HOST_SOCKET_PORT_RANGE is set to %s as [%u, %u].", HCCL_AUTO_PORT_CONFIG, autoSocketPortRange.min,
     242              :             autoSocketPortRange.max);
     243            1 :         return hcclSocketPortRange;
     244              :     }
     245              : 
     246              :     // the environment variable is set to an empty string
     247            8 :     socketPortRange.erase(std::remove(socketPortRange.begin(), socketPortRange.end(), ' '), socketPortRange.end());
     248            8 :     if (socketPortRange.empty()) {
     249            0 :         return hcclSocketPortRange;
     250              :     }
     251              : 
     252              :     // load ranges from string
     253            8 :     SplitHcclSocketPortRange(envName, socketPortRange, hcclSocketPortRange);
     254            3 :     CHK_PRT_THROW(
     255              :         hcclSocketPortRange.size() == 0,
     256              :         HCCL_ERROR("Load empty port range from HCCL_HOST_SOCKET_PORT_RANGE, should not empty, please check."),
     257              :         InvalidParamsException, "parser portRange fail.");
     258              : 
     259            3 :     PrintSocketPortRange(envName, hcclSocketPortRange);
     260            3 :     return hcclSocketPortRange;
     261           14 : }
     262              : 
     263              : constexpr u32 HCCL_RDMA_TC_BASE = 4; // RDMATrafficClass需要是4的整数倍
     264            4 : void CheckRDMATrafficClass(const u32& rdmaTrafficClass)
     265              : {
     266            4 :     if (rdmaTrafficClass % HCCL_RDMA_TC_BASE != 0) {
     267           14 :         RPT_ENV_ERR(
     268              :             true, "EI0001", std::vector<std::string>({"value", "env", "expect"}),
     269              :             std::vector<std::string>(
     270              :                 {std::to_string(rdmaTrafficClass), "HCCL_RDMA_TC", "value should be multiple of four"}));
     271            3 :         HCCL_ERROR("rdmaTrafficClass[%u] is not a multiple of [%u]", rdmaTrafficClass, HCCL_RDMA_TC_BASE);
     272            1 :         THROW<InvalidParamsException>(
     273            2 :             StringFormat("rdmaTrafficClass[%u] is not a multiple of [%u]", rdmaTrafficClass, HCCL_RDMA_TC_BASE));
     274              :     }
     275            5 : }
     276              : 
     277              : constexpr u32 BYTES_PER_KB = 1024; // 单位换算
     278            2 : void ConvertUnitQpThreshold(u32& multiQpThreshold)
     279              : {
     280            6 :     HCCL_RUN_INFO(
     281              :         "[Init][TransferUnitQpThreshold]Env config HCCL_MULTI_QP_THRESHOLD is %u[KB], converted to %u[B] for "
     282              :         "subsequant use.",
     283              :         multiQpThreshold, multiQpThreshold * BYTES_PER_KB);
     284            2 :     multiQpThreshold *= BYTES_PER_KB;
     285            2 : }
     286              : 
     287            1 : static void ParseAlgoLevel(const std::string& algoLevel, u32& level, HcclAlgoType& algoType)
     288              : {
     289            1 :     std::size_t found = algoLevel.find(':');
     290            1 :     if ((found == 0) || (found == (algoLevel.length() - 1))) {
     291            0 :         THROW<InvalidParamsException>("algo config is invalid.");
     292              :     }
     293            1 :     if (found == std::string::npos) {
     294            1 :         THROW<InvalidParamsException>("algoLevel cannot find \":\".");
     295              :     }
     296              : 
     297            0 :     std::string orginalLevel = algoLevel.substr(0, found);
     298            0 :     std::string orginalAlgo = algoLevel.substr(found + 1);
     299              : 
     300              :     const std::map<std::string, u32> hcclAlgoLevelMap
     301              :         = {{"level0", HCCL_ALGO_LEVEL_0},
     302              :            {"level1", HCCL_ALGO_LEVEL_1},
     303              :            {"level2", HCCL_ALGO_LEVEL_2},
     304            0 :            {"level3", HCCL_ALGO_LEVEL_3}};
     305              : 
     306              :     const std::map<std::string, HcclAlgoType> hcclAlgoTypeMap = {
     307            0 :         {"null", HcclAlgoType::HCCL_ALGO_TYPE_NULL},
     308            0 :         {"ring", HcclAlgoType::HCCL_ALGO_TYPE_RING},
     309            0 :         {"pipeline", HcclAlgoType::HCCL_ALGO_TYPE_PIPELINE},
     310            0 :         {"fullmesh", HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH},
     311            0 :         {"H-D_R", HcclAlgoType::HCCL_ALGO_TYPE_HDR},
     312            0 :         {"pairwise", HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE},
     313            0 :         {"NHR", HcclAlgoType::HCCL_ALGO_TYPE_NHR},
     314            0 :         {"NB", HcclAlgoType::HCCL_ALGO_TYPE_NB},
     315            0 :         {"NA", HcclAlgoType::HCCL_ALGO_TYPE_NA},
     316            0 :         {"NHR_V1", HcclAlgoType::HCCL_ALGO_TYPE_NHR_V1},
     317            0 :         {"AHC", HcclAlgoType::HCCL_ALGO_TYPE_AHC},
     318            0 :     };
     319              : 
     320            0 :     auto iterAlgoLevel = hcclAlgoLevelMap.find(orginalLevel);
     321            0 :     if (iterAlgoLevel == hcclAlgoLevelMap.end()) {
     322            0 :         THROW<InvalidParamsException>(
     323            0 :             StringFormat("algo config is invalid, level %s is not supported.", orginalLevel.c_str()));
     324              :     }
     325              : 
     326            0 :     auto iterAlgoType = hcclAlgoTypeMap.find(orginalAlgo);
     327            0 :     if (iterAlgoType == hcclAlgoTypeMap.end()) {
     328            0 :         THROW<InvalidParamsException>(
     329            0 :             StringFormat("algo config is invalid, algo %s is not supported.", orginalAlgo.c_str()));
     330              :     }
     331              : 
     332            0 :     level = iterAlgoLevel->second;
     333            0 :     algoType = iterAlgoType->second;
     334            0 : }
     335              : 
     336            1 : std::vector<HcclAlgoType> CastAlgoTypeVec(const std::string& s)
     337              : {
     338            1 :     std::vector<HcclAlgoType> algoTypeVec(HCCL_ALGO_LEVEL_NUM);
     339            1 :     std::string algoConfig = s;
     340            1 :     algoConfig.erase(std::remove(algoConfig.begin(), algoConfig.end(), ' '), algoConfig.end());
     341              : 
     342            5 :     for (u32 i = 0; i < HCCL_ALGO_LEVEL_NUM; i++) {
     343            4 :         algoTypeVec[i] = HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT;
     344              :     }
     345              : 
     346            1 :     if (algoConfig.empty()) {
     347            0 :         HCCL_RUN_INFO("hccl algo config is empty, HCCL use built-in algo selection.");
     348            0 :         return algoTypeVec;
     349              :     }
     350              : 
     351            1 :     std::vector<std::string> algoLevels = SplitString(algoConfig, ';');
     352            1 :     if (algoLevels.size() > HCCL_ALGO_LEVEL_NUM) {
     353            0 :         THROW<InvalidParamsException>(
     354            0 :             StringFormat("The number of algo levels is greater than %u.", HCCL_ALGO_LEVEL_NUM));
     355              :     }
     356            1 :     for (const auto& algoLevel : algoLevels) {
     357            1 :         u32 level = 0;
     358            1 :         HcclAlgoType algo = HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT;
     359            1 :         ParseAlgoLevel(algoLevel, level, algo);
     360              :         // 检查是否存在重复配置level
     361            0 :         if (algoTypeVec[level] != HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT) {
     362            0 :             THROW<InvalidParamsException>(
     363            0 :                 StringFormat("hccl algo config[%s] is invalid. expect: levelX:algo1;levelY:algo2", algoConfig.c_str()));
     364              :         }
     365            0 :         algoTypeVec[level] = algo;
     366              :     }
     367              : 
     368            0 :     DevType devType = HrtGetDeviceType(); // 910A3场景只支持level0为ring算法
     369            0 :     if (devType == DevType::DEV_TYPE_910A3 && algoTypeVec[HCCL_ALGO_LEVEL_0] != HcclAlgoType::HCCL_ALGO_TYPE_RING) {
     370            0 :         algoTypeVec[HCCL_ALGO_LEVEL_0] = HcclAlgoType::HCCL_ALGO_TYPE_RING;
     371              :     }
     372              : 
     373            0 :     return algoTypeVec;
     374            3 : }
     375              : 
     376            2 : HcclResult SplitHcclOpType(const std::string& algoConfig, std::vector<std::string>& algos)
     377              : {
     378            2 :     std::string remainAlgoConfig;
     379            2 :     std::size_t found = algoConfig.find("/");
     380            2 :     if ((found == 0) || (found == (algoConfig.length() - 1))) {
     381            0 :         HCCL_ERROR("[Split][SplitHcclOpType] algo config is invalid.");
     382            0 :         return HCCL_E_PARA;
     383            2 :     } else if (found != std::string::npos) {
     384            0 :         remainAlgoConfig = algoConfig.substr(found + 1);
     385              :     }
     386            2 :     algos.push_back(algoConfig.substr(0, found));
     387            2 :     if (!remainAlgoConfig.empty()) {
     388            0 :         CHK_RET(SplitHcclOpType(remainAlgoConfig, algos));
     389              :     }
     390            2 :     return HCCL_SUCCESS;
     391            2 : }
     392              : 
     393              : // 新的逐算法的配置和原有的统一配置只可使用一种,发现同时存在时报错
     394            2 : HcclResult CheckAlgoConfigValid(std::vector<std::string>& algos, bool& anyCommonConfig, bool& anySpecificConfig)
     395              : {
     396            4 :     for (std::string& algConfig : algos) {
     397            2 :         std::size_t found = algConfig.find("=");
     398            2 :         if ((found == 0) || (found == (algConfig.length() - 1))) {
     399            0 :             HCCL_ERROR("[Split][CheckAlgoConfigValid] algo config is invalid.");
     400            0 :             return HCCL_E_PARA;
     401            2 :         } else if (found != std::string::npos) {
     402            0 :             anySpecificConfig = true;
     403              :         } else {
     404            2 :             anyCommonConfig = true;
     405              :         }
     406              :     }
     407            2 :     if (anyCommonConfig && anySpecificConfig) {
     408            0 :         HCCL_ERROR("[CheckAlgoConfigValid]should not set both algo config way");
     409            0 :         return HCCL_E_PARA;
     410              :     }
     411            2 :     if (anyCommonConfig && algos.size() > 1) {
     412            0 :         HCCL_ERROR("[CheckAlgoConfigValid]should only set one common config");
     413            0 :         return HCCL_E_PARA;
     414              :     }
     415            2 :     return HCCL_SUCCESS;
     416              : }
     417              : 
     418            2 : HcclResult ParserHcclAlgoLevel(const std::string& algoLevel, u32& level, HcclAlgoType& algoType)
     419              : {
     420            2 :     std::size_t found = algoLevel.find(":");
     421            2 :     if ((found == 0) || (found == (algoLevel.length() - 1))) {
     422            0 :         HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid.");
     423            0 :         return HCCL_E_PARA;
     424              :     }
     425            2 :     if (found == std::string::npos) {
     426            1 :         THROW<InvalidParamsException>("algoLevel cannot find \":\".");
     427              :     }
     428              : 
     429            1 :     std::string orginalLevel = algoLevel.substr(0, found);
     430            1 :     std::string orginalAlgo = algoLevel.substr(found + 1);
     431              : 
     432              :     const std::map<std::string, u32> hcclAlgoLevelMap
     433              :         = {{"level0", HCCL_ALGO_LEVEL_0},
     434              :            {"level1", HCCL_ALGO_LEVEL_1},
     435              :            {"level2", HCCL_ALGO_LEVEL_2},
     436            6 :            {"level3", HCCL_ALGO_LEVEL_3}};
     437              : 
     438              :     const std::map<std::string, HcclAlgoType> hcclAlgoTypeMap = {
     439            0 :         {"null", HcclAlgoType::HCCL_ALGO_TYPE_NULL},
     440            0 :         {"ring", HcclAlgoType::HCCL_ALGO_TYPE_RING},
     441            0 :         {"pipeline", HcclAlgoType::HCCL_ALGO_TYPE_PIPELINE},
     442            0 :         {"fullmesh", HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH},
     443            0 :         {"H-D_R", HcclAlgoType::HCCL_ALGO_TYPE_HDR},
     444            0 :         {"pairwise", HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE},
     445            0 :         {"NHR", HcclAlgoType::HCCL_ALGO_TYPE_NHR},
     446            0 :         {"NB", HcclAlgoType::HCCL_ALGO_TYPE_NB},
     447            0 :         {"NA", HcclAlgoType::HCCL_ALGO_TYPE_NA},
     448            0 :         {"NHR_V1", HcclAlgoType::HCCL_ALGO_TYPE_NHR_V1},
     449            0 :         {"AHC", HcclAlgoType::HCCL_ALGO_TYPE_AHC},
     450           13 :     };
     451              : 
     452            1 :     auto iterAlgoLevel = hcclAlgoLevelMap.find(orginalLevel);
     453            1 :     if (iterAlgoLevel == hcclAlgoLevelMap.end()) {
     454            0 :         HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid, level %s is not supported.", orginalLevel.c_str());
     455            0 :         return HCCL_E_PARA;
     456              :     }
     457              : 
     458            1 :     auto iterAlgoType = hcclAlgoTypeMap.find(orginalAlgo);
     459            1 :     if (iterAlgoType == hcclAlgoTypeMap.end()) {
     460            3 :         HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid, algo %s is not supported.", orginalAlgo.c_str());
     461            1 :         return HCCL_E_PARA;
     462              :     }
     463              : 
     464            0 :     level = iterAlgoLevel->second;
     465            0 :     algoType = iterAlgoType->second;
     466              : 
     467            0 :     return HCCL_SUCCESS;
     468            3 : }
     469              : 
     470              : const std::map<HcclAlgoType, std::string> HcclAlgoTypeMap = {
     471              :     {HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT, "default"},   {HcclAlgoType::HCCL_ALGO_TYPE_RING, "ring"},
     472              :     {HcclAlgoType::HCCL_ALGO_TYPE_PIPELINE, "pipeline"}, {HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH, "fullmesh"},
     473              :     {HcclAlgoType::HCCL_ALGO_TYPE_HDR, "HDR"},           {HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE, "pairwise"},
     474              :     {HcclAlgoType::HCCL_ALGO_TYPE_NHR, "NHR"},           {HcclAlgoType::HCCL_ALGO_TYPE_NB, "NB"},
     475              :     {HcclAlgoType::HCCL_ALGO_TYPE_NULL, "null"},         {HcclAlgoType::HCCL_ALGO_TYPE_NA, "NA"},
     476              :     {HcclAlgoType::HCCL_ALGO_TYPE_NHR_V1, "NHR_V1"},     {HcclAlgoType::HCCL_ALGO_TYPE_AHC, "AHC"},
     477              : };
     478              : 
     479            3 : HcclResult SplitHcclAlgoLevel(const std::string& algoConfig, std::vector<std::string>& algos)
     480              : {
     481            3 :     std::string remainAlgoConfig;
     482            3 :     std::size_t found = algoConfig.find(";");
     483            3 :     if ((found == 0) || (found == (algoConfig.length() - 1))) {
     484            0 :         HCCL_ERROR("[Split][HcclAlgoLevel] algo config is invalid.");
     485            0 :         return HCCL_E_PARA;
     486            3 :     } else if (found != std::string::npos) {
     487            1 :         remainAlgoConfig = algoConfig.substr(found + 1);
     488              :     } else {
     489              :         // 最后一组配置,剩余的字符串为空
     490              :     }
     491            3 :     algos.push_back(algoConfig.substr(0, found));
     492              : 
     493            3 :     if (algos.size() > HCCL_ALGO_LEVEL_NUM) {
     494            0 :         HCCL_ERROR("[Split][HcclAlgoLevel] algo config is invalid. algo level is more than %u.", HCCL_ALGO_LEVEL_NUM);
     495            0 :         return HCCL_E_PARA;
     496              :     }
     497            3 :     if (!remainAlgoConfig.empty()) {
     498            1 :         CHK_RET(SplitHcclAlgoLevel(remainAlgoConfig, algos));
     499              :     }
     500              : 
     501            3 :     return HCCL_SUCCESS;
     502            3 : }
     503              : 
     504            2 : HcclResult ParseAlgoString(std::string opName, std::string& algoString, std::vector<HcclAlgoType>& algType)
     505              : {
     506            2 :     algType = std::vector<HcclAlgoType>(HCCL_ALGO_LEVEL_NUM, HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT);
     507            2 :     std::vector<std::string> algoLevels;
     508            2 :     HcclResult ret = SplitHcclAlgoLevel(algoString, algoLevels);
     509            2 :     CHK_PRT_RET(
     510              :         ret != HCCL_SUCCESS,
     511              :         HCCL_ERROR(
     512              :             "[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "
     513              :             "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
     514              :             algoString.c_str()),
     515              :         ret);
     516            2 :     for (auto algoLevel : algoLevels) {
     517            2 :         u32 level = 0;
     518            2 :         HcclAlgoType algo = HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT;
     519            2 :         ret = ParserHcclAlgoLevel(algoLevel, level, algo);
     520            4 :         CHK_PRT_RET(
     521              :             ret != HCCL_SUCCESS,
     522              :             HCCL_ERROR(
     523              :                 "[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "
     524              :                 "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
     525              :                 algoString.c_str()),
     526              :             ret);
     527              :         // 检查是否存在重复配置level
     528            0 :         if (algType[level] != HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT) {
     529            0 :             HCCL_ERROR(
     530              :                 "[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "
     531              :                 "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
     532              :                 algoString.c_str());
     533            0 :             return HCCL_E_PARA;
     534              :         }
     535            0 :         algType[level] = algo;
     536            2 :     }
     537            0 :     auto level0Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_0]);
     538            0 :     auto level1Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_1]);
     539            0 :     auto level2Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_2]);
     540            0 :     auto level3Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_3]);
     541            0 :     HCCL_RUN_INFO(
     542              :         "hccl algo op %s config: level0:%s, level1:%s, level2:%s, level3:%s", opName.c_str(),
     543              :         level0Iter->second.c_str(), level1Iter->second.c_str(), level2Iter->second.c_str(), level3Iter->second.c_str());
     544            0 :     return HCCL_SUCCESS;
     545            2 : }
     546              : 
     547              : HcclResult
     548            2 : SetCommonAlgType(std::vector<std::string>& algos, std::map<OpType, std::vector<HcclAlgoType>>& hcclAlgoConfig)
     549              : {
     550            2 :     std::vector<HcclAlgoType> algType;
     551            9 :     CHK_RET(ParseAlgoString("all op type", algos[0], algType));
     552            0 :     for (auto opType : OP_TYPE_SET) {
     553            0 :         hcclAlgoConfig[opType] = algType;
     554              :     }
     555            0 :     return HCCL_SUCCESS;
     556            2 : }
     557              : 
     558              : HcclResult
     559            0 : SetSpecificAlgType(std::vector<std::string>& algos, std::map<OpType, std::vector<HcclAlgoType>>& hcclAlgoConfig)
     560              : {
     561              :     std::map<std::string, OpType> hcclOpTypeMap = {
     562            0 :         {"broadcast", OpType::BROADCAST},
     563            0 :         {"allreduce", OpType::ALLREDUCE},
     564            0 :         {"reduce", OpType::REDUCE},
     565            0 :         {"send", OpType::SEND},
     566            0 :         {"receive", OpType::RECV},
     567            0 :         {"allgather", OpType::ALLGATHER},
     568            0 :         {"reducescatter", OpType::REDUCESCATTER},
     569            0 :         {"alltoall", OpType::ALLTOALL},
     570            0 :         {"gather", OpType::GATHER},
     571            0 :         {"scatter", OpType::SCATTER},
     572            0 :         {"sendrecv", OpType::BATCHSENDRECV},
     573            0 :     };
     574            0 :     for (std::string& algConfig : algos) {
     575            0 :         std::size_t found = algConfig.find("=");
     576            0 :         std::string opStringName = algConfig.substr(0, found);
     577            0 :         if (hcclOpTypeMap.find(opStringName) != hcclOpTypeMap.end()) {
     578            0 :             OpType optype = hcclOpTypeMap[opStringName];
     579            0 :             std::string remainAlgoConfig = algConfig.substr(found + 1);
     580            0 :             std::vector<HcclAlgoType> algType;
     581            0 :             CHK_RET(ParseAlgoString(opStringName, remainAlgoConfig, algType));
     582            0 :             if (algType[0] == HcclAlgoType::HCCL_ALGO_TYPE_NULL) {
     583            0 :                 HCCL_ERROR("[SetSpecificAlgType] specific config level0 not support null type.");
     584            0 :                 return HCCL_E_PARA;
     585              :             }
     586            0 :             hcclAlgoConfig[optype] = algType;
     587            0 :         } else {
     588            0 :             HCCL_ERROR(
     589              :                 "[SetSpecificAlgType] specific config optype[%s] is invalid, please check", opStringName.c_str());
     590            0 :             return HCCL_E_PARA;
     591              :         }
     592            0 :     }
     593            0 :     if (hcclAlgoConfig.find(OpType::ALLTOALL) != hcclAlgoConfig.end()) {
     594            0 :         hcclAlgoConfig[OpType::ALLTOALLV] = hcclAlgoConfig[OpType::ALLTOALL];
     595            0 :         hcclAlgoConfig[OpType::ALLTOALLVC] = hcclAlgoConfig[OpType::ALLTOALL];
     596              :     }
     597            0 :     return HCCL_SUCCESS;
     598            0 : }
     599              : 
     600            2 : std::map<OpType, std::vector<HcclAlgoType>> SetHcclAlgoConfig(const std::string& hcclAlgo)
     601              : {
     602            2 :     std::string algoConfig = hcclAlgo;
     603            2 :     algoConfig.erase(std::remove(algoConfig.begin(), algoConfig.end(), ' '), algoConfig.end());
     604            2 :     std::map<OpType, std::vector<HcclAlgoType>> hcclAlgoConfig;
     605            2 :     if (algoConfig.empty()) {
     606            0 :         HCCL_RUN_INFO("hccl algo config is empty, HCCL use built-in algo selection.");
     607            0 :         return hcclAlgoConfig;
     608              :     }
     609            2 :     std::vector<std::string> algoPerOptype;
     610            2 :     HcclResult splitRet = SplitHcclOpType(algoConfig, algoPerOptype);
     611            2 :     if (splitRet != HCCL_SUCCESS) {
     612            0 :         THROW<InvalidParamsException>(StringFormat(
     613              :             "Env HCCL_ALGO config \"%s\" is invalid. example [level0:NA;level1:NHR] or"
     614              :             "[allreduce=level0:NA;level1:ring/allgather=level0:NA;level1:H-D_R]",
     615              :             hcclAlgo.c_str()));
     616              :     }
     617              : 
     618            2 :     bool anyCommonConfig = false;
     619            2 :     bool anySpecificConfig = false;
     620            2 :     HcclResult checkRet = CheckAlgoConfigValid(algoPerOptype, anyCommonConfig, anySpecificConfig);
     621            2 :     if (checkRet != HCCL_SUCCESS) {
     622            0 :         THROW<InvalidParamsException>(StringFormat(
     623              :             "Env HCCL_ALGO config \"%s\" is invalid. example [level0:NA;level1:NHR] or"
     624              :             "[allreduce=level0:NA;level1:ring/allgather=level0:NA;level1:H-D_R]",
     625              :             hcclAlgo.c_str()));
     626              :     }
     627            2 :     HcclResult ret = HCCL_SUCCESS;
     628            2 :     if (anyCommonConfig) {
     629            2 :         ret = SetCommonAlgType(algoPerOptype, hcclAlgoConfig);
     630              :     } else {
     631            0 :         ret = SetSpecificAlgType(algoPerOptype, hcclAlgoConfig);
     632              :     }
     633            1 :     if (ret != HCCL_SUCCESS) {
     634            2 :         THROW<InvalidParamsException>(StringFormat(
     635              :             "Env HCCL_ALGO config \"%s\" is invalid. example [level0:NA;level1:NHR] or"
     636              :             "[allreduce=level0:NA;level1:ring/allgather=level0:NA;level1:H-D_R]",
     637              :             hcclAlgo.c_str()));
     638              :     }
     639            0 :     return hcclAlgoConfig;
     640            6 : }
     641              : 
     642           11 : HcclAccelerator CastHcclAccelerator(const std::string& s)
     643              : {
     644           11 :     HcclAccelerator mode;
     645           11 :     if (s == "AI_CPU" || s == "AICPU_TS" || s == "AICPU_CacheDisable") {
     646            3 :         mode = HcclAccelerator::AICPU_TS;
     647            8 :     } else if (s == "AIV") {
     648            1 :         mode = HcclAccelerator::AIV;
     649            7 :     } else if (s == "CCU_MS") {
     650            1 :         mode = HcclAccelerator::CCU_MS;
     651            6 :     } else if (s == "CCU_SCHED") {
     652            2 :         mode = HcclAccelerator::CCU_SCHED;
     653              :     } else {
     654           12 :         HCCL_ERROR(
     655              :             "Env HCCL_OP_EXPANSION_MODE config do not support %s, it should be one of [AI_CPU, AICPU_TS, "
     656              :             "AICPU_CacheDisable, AIV, CCU_MS, CCU_SCHED].",
     657              :             s.c_str());
     658            8 :         THROW<InvalidParamsException>(StringFormat(
     659              :             "Env HCCL_OP_EXPANSION_MODE config \"%s\" is invalid."
     660              :             "it should be one of [AI_CPU, AICPU_TS, AICPU_CacheDisable, AIV, CCU_MS, CCU_SCHED].",
     661              :             s.c_str()));
     662              :     }
     663            7 :     return mode;
     664              : }
     665              : 
     666            5 : s32 CastSocketFamily(const std::string& s)
     667              : {
     668              :     s32 hcclSocketFamily;
     669            5 :     if (s == "AF_INET") {
     670            1 :         hcclSocketFamily = AF_INET;
     671            4 :     } else if (s == "AF_INET6") {
     672            2 :         hcclSocketFamily = AF_INET6;
     673              :     } else {
     674            2 :         hcclSocketFamily = -1;
     675            2 :         THROW<InvalidParamsException>(StringFormat(
     676              :             "environmental variable HCCL_SOCKET_FAMILY[%s] is invalid. it should "
     677              :             "be \"AF_INET\" or \"AF_INET6\".",
     678              :             s.c_str()));
     679              :     }
     680            3 :     return hcclSocketFamily;
     681              : }
     682              : 
     683           11 : std::string GetCannVersionPath(const std::string& cannEnvStr, const std::string& keyStr)
     684              : {
     685           11 :     std::string cannVersionPath;
     686           11 :     std::string tempPath; // 存放临时路径
     687              :     // 查找cann安装路径
     688          494 :     for (u32 i = 0; i < cannEnvStr.length(); ++i) {
     689              :         // 环境变量中存放的每段路径之间以':'隔开
     690          484 :         if (cannEnvStr[i] != ':') {
     691          483 :             tempPath += cannEnvStr[i];
     692              :         }
     693              :         // 对存放CANN版本文件的路径进行搜索, 有两种情况
     694              :         // 一种是*/latest/version.cfg
     695              :         // 另一种是*/runtime/version.info
     696          484 :         if (cannEnvStr[i] == ':' || i == cannEnvStr.length() - 1) {
     697           12 :             size_t found = tempPath.find(keyStr);
     698           12 :             if (found == string::npos) {
     699           11 :                 tempPath.clear();
     700           11 :                 continue;
     701              :             }
     702              :             // 防止出现类似/runtime*/的情况
     703            1 :             if (tempPath.length() <= found + keyStr.length() || tempPath[found + keyStr.length()] == '/') {
     704            1 :                 cannVersionPath = tempPath.substr(0, found + keyStr.length());
     705            1 :                 break;
     706              :             }
     707            0 :             tempPath.clear();
     708              :         }
     709              :     }
     710              :     // 路径为空
     711           11 :     if (cannVersionPath.empty()) {
     712           20 :         return "NotFound";
     713              :     }
     714            1 :     return cannVersionPath;
     715           11 : }
     716              : 
     717            1 : std::string LoadCannVersionInfoFile(const std::string& realName, const std::string& keyStr)
     718              : {
     719            1 :     std::string cannVersion;
     720              :     // 打开该文件前,判断该文件路径是否有效、规范
     721            1 :     char realFile[PATH_MAX] = {0};
     722            1 :     if (realpath(realName.c_str(), realFile) == nullptr) {
     723            0 :         HCCL_INFO("[CannVersion][Verification]cann version path %s is not a valid real path", realName.c_str());
     724            0 :         return "";
     725              :     }
     726            3 :     HCCL_INFO("Load CannVersion InfoFile in %s", realFile);
     727              : 
     728              :     // realFile转str,然后open这个str
     729            1 :     std::ifstream infile(realFile, std::ifstream::in);
     730              : 
     731            1 :     if (!infile.is_open()) {
     732            3 :         HCCL_INFO("[CannVersion][Verification]%s does not exist.", realFile);
     733            2 :         return "";
     734              :     }
     735              : 
     736              :     // 逐行读取,结果放在line中,寻找带有keyStr的字符串
     737            0 :     string line;
     738            0 :     s32 maxRows = 100; // 在文件中读取的最长行数为100,避免超大文件长时间读取
     739            0 :     while (getline(infile, line)) {
     740            0 :         --maxRows;
     741            0 :         if (maxRows < 0) {
     742            0 :             HCCL_WARNING("[CannVersion][Verification]version file content is too long.");
     743            0 :             return "";
     744              :         }
     745            0 :         u32 found = line.find(keyStr);
     746              :         // 版本字段的两种模式
     747              :         // runtime目录下, version.info文件, Version=1.83.T8.0.B128
     748              :         // latest目录下, version.cfg文件, runtime_running_version=[1.83.T8.0.B128:CANN-1.83]
     749            0 :         if (found == 0) {
     750            0 :             u32 startPos = keyStr.length();                  // 版本字符串开始位置
     751            0 :             u32 endPos = min(line.find(":"), line.length()); // 版本字符串在":"或结尾处结束
     752              :             // 版本字符串为空
     753            0 :             if (endPos <= startPos) {
     754            0 :                 HCCL_WARNING("[CannVersion][Verification]cannVersion is invalid.");
     755            0 :                 return "";
     756              :             }
     757              : 
     758            0 :             u32 len = endPos - startPos;              // 版本字符串长度
     759            0 :             cannVersion = line.substr(startPos, len); // 从keyStr截断
     760            0 :             HCCL_INFO("[Parse][CannVersion]success, CannVersion is %s ", cannVersion.c_str());
     761            0 :             break;
     762              :         }
     763              :     }
     764            0 :     infile.close();
     765            0 :     return cannVersion;
     766            1 : }
     767              : 
     768            6 : std::string CastCannVersion(const std::string& cannEnv)
     769              : {
     770            6 :     std::string cannVersionPath = GetCannVersionPath(cannEnv, "/runtime");
     771            6 :     if (cannVersionPath != "NotFound") {
     772            1 :         cannVersionPath += "/version.info";
     773            1 :         std::string cannVersion = LoadCannVersionInfoFile(cannVersionPath, "Version=");
     774            1 :         return cannVersion;
     775            0 :     }
     776              : 
     777            5 :     cannVersionPath = GetCannVersionPath(cannEnv, "/latest");
     778            5 :     if (cannVersionPath != "NotFound") {
     779            0 :         cannVersionPath += "/version.cfg";
     780            0 :         std::string cannVersion = LoadCannVersionInfoFile(cannVersionPath, "runtime_running_version=[");
     781            0 :         return cannVersion;
     782            0 :     }
     783              : 
     784           15 :     HCCL_INFO("cannot found version file in %s.", cannEnv.c_str());
     785           10 :     return "";
     786            6 : }
     787              : 
     788           18 : std::vector<std::string> SplitDfsConfig(const std::string& str, char delimiter)
     789              : {
     790           18 :     std::vector<std::string> tokens;
     791           18 :     std::istringstream stream(str);
     792           18 :     std::string token;
     793              : 
     794           44 :     while (std::getline(stream, token, delimiter)) {
     795           26 :         tokens.push_back(token);
     796              :     }
     797           18 :     if (stream.peek() != EOF) {
     798            0 :         std::string remaining;
     799            0 :         std::getline(stream, remaining);
     800            0 :         tokens.push_back(remaining);
     801            0 :     }
     802           18 :     if (!str.empty() && str.back() == delimiter) {
     803            0 :         tokens.push_back("");
     804              :     }
     805           18 :     return tokens;
     806           18 : }
     807              : 
     808            8 : void CastDfsConfigParseTaskExceptionEnable(bool& taskExceptionEnable, const std::string configValue)
     809              : {
     810            8 :     if (configValue == "off") {
     811            2 :         taskExceptionEnable = false;
     812            6 :         HCCL_WARNING("env[HCCL_DFS_CONFIG] task_exception was configed to [%s]", configValue.c_str());
     813            6 :     } else if (configValue == "on") {
     814            5 :         taskExceptionEnable = true;
     815              :     } else {
     816            1 :         THROW<InvalidParamsException>(
     817            2 :             StringFormat("env[HCCL_DFS_CONFIG] please set task_exception to 'on' or 'off'.", configValue.c_str()));
     818              :     }
     819            7 : }
     820              : 
     821            0 : void CastDfsConfigParseClusterHeartBeatEnable(bool& clusterHeartBeatEnable, const std::string configValue)
     822              : {
     823            0 :     if (configValue == "off") {
     824            0 :         clusterHeartBeatEnable = false;
     825            0 :         HCCL_WARNING("env[HCCL_DFS_CONFIG] cluster_heartbeat was configed to [%s]", configValue.c_str());
     826            0 :     } else if (configValue == "on") {
     827            0 :         clusterHeartBeatEnable = true;
     828              :     } else {
     829            0 :         THROW<InvalidParamsException>(
     830            0 :             StringFormat("env[HCCL_DFS_CONFIG] please set cluster_heartbeat to 'on' or 'off'.", configValue.c_str()));
     831              :     }
     832            0 : }
     833              : 
     834            0 : void CastDfsConfigParseRankConsistentState(int32_t& rankConsistentState, const std::string configValue)
     835              : {
     836            0 :     if (configValue == "off") {
     837            0 :         rankConsistentState = -1;
     838            0 :     } else if (configValue == "first") {
     839            0 :         rankConsistentState = 0;
     840            0 :     } else if (configValue == "on") {
     841            0 :         rankConsistentState = 1;
     842              :     } else {
     843            0 :         THROW<InvalidParamsException>(StringFormat(
     844              :             "env[HCCL_DFS_CONFIG] please set inconsistent_check to '-1' or '0' or '1'.", configValue.c_str()));
     845              :     }
     846            0 : }
     847              : 
     848            9 : DfsConfig CastDfsConfig(const std::string& dfsConfigEnv)
     849              : {
     850            9 :     constexpr std::size_t DFS_CONFIG_ITEM_NUM = 3;
     851              :     const std::array<std::string, DFS_CONFIG_ITEM_NUM> dfsItemName
     852           18 :         = {"task_exception", "cluster_heartbeat", "inconsistent_check"};
     853            9 :     bool taskExceptionEnable = true;
     854            9 :     bool clusterHeartBeatEnable = true;
     855            9 :     int32_t rankConsistentState = 0;
     856            9 :     std::string dfsConfigEnvCopy = dfsConfigEnv;
     857            9 :     dfsConfigEnvCopy.erase(std::remove(dfsConfigEnvCopy.begin(), dfsConfigEnvCopy.end(), ' '), dfsConfigEnvCopy.end());
     858            9 :     auto items = SplitDfsConfig(dfsConfigEnvCopy, ',');
     859           16 :     for (const auto& item : items) {
     860            9 :         auto itemPair = SplitDfsConfig(item, ':');
     861            9 :         constexpr std::size_t ITEM_SIZE = 2;
     862            9 :         if (itemPair.size() != ITEM_SIZE
     863            9 :             || std::find(dfsItemName.begin(), dfsItemName.end(), itemPair[0]) == dfsItemName.end()) {
     864            2 :             THROW<InvalidParamsException>(StringFormat(
     865              :                 "env[HCCL_DFS_CONFIG] value[%s] is invalid, please check, example [task_exception:on]",
     866              :                 dfsConfigEnv.c_str()));
     867              :         }
     868            8 :         if (itemPair[0] == dfsItemName[0]) {
     869            9 :             CastDfsConfigParseTaskExceptionEnable(taskExceptionEnable, itemPair[1]);
     870            0 :         } else if (itemPair[0] == dfsItemName[1]) {
     871            0 :             CastDfsConfigParseClusterHeartBeatEnable(clusterHeartBeatEnable, itemPair[1]);
     872            0 :         } else if (itemPair[0] == dfsItemName[2]) {
     873            0 :             CastDfsConfigParseRankConsistentState(rankConsistentState, itemPair[1]);
     874              :         }
     875            9 :     }
     876            7 :     DfsConfig config{taskExceptionEnable, clusterHeartBeatEnable, rankConsistentState};
     877              : 
     878            7 :     return config;
     879           13 : }
     880              : 
     881              : /*----------------------------- validate functions -------------------------*/
     882            6 : void CheckExecTimeOut(const u32& timeOut)
     883              : {
     884            6 :     DevType devType = HrtGetDeviceType();
     885           12 :     if (devType == DevType::DEV_TYPE_910A2 || devType == DevType::DEV_TYPE_910A3 || devType == DevType::DEV_TYPE_950
     886           12 :         || devType == DevType::DEV_TYPE_960) {
     887              :         // 910A2和910A3算子超时时间范围0s-2147483647s,其中0代表永不超时
     888            5 :         CheckRange<u32>(timeOut, 0, HCCL_EXEC_TIME_OUT_S_910A3);
     889              :     } else {
     890              :         // 非910A2和910A3算子超时时间范围1s-17340s
     891            1 :         CheckRange<u32>(timeOut, 1, HCCL_EXEC_TIME_OUT_S);
     892              :     }
     893            5 : }
     894              : 
     895           12 : void CheckFilePath(const string& filePath)
     896              : {
     897           12 :     if (filePath.length() >= (PATH_MAX) || filePath.length() == 0) {
     898            2 :         THROW<InvalidParamsException>(StringFormat(
     899              :             "env[HCCL_WHITELIST_FILE] or env[HCCL_RDMA_QP_PORT_CONFIG_PATH] is invalid, len is %u, should be (0,4096)",
     900              :             filePath.length()));
     901              :     }
     902           10 : }
     903              : 
     904            9 : void CheckRdmaTimeout(const u32& timeout)
     905              : {
     906              :     // HCCL_RDMA_TIMEOUT 合法范围为:[0, 31],超出31按照0进行处理,表示永不超时
     907              :     // 此处为空实现,原因为非法值在 Str2T<u32> 里面已经处理
     908              :     (void)timeout;
     909            9 : }
     910              : 
     911              : /*-------------------------- post process functions -------------------------*/
     912           10 : void SetRealPath(string& filePath)
     913              : {
     914           10 :     char realFile[PATH_MAX] = {0};
     915           10 :     if (realpath(filePath.c_str(), realFile) == nullptr) {
     916            2 :         THROW<InvalidParamsException>(
     917            6 :             StringFormat("[Init][EnvVarParam]path %s is not a valid real path", filePath.c_str()));
     918              :     }
     919            8 :     filePath = std::string(realFile);
     920            8 : }
     921              : 
     922            5 : void ProcExecTimeOut(u32& timeOut)
     923              : {
     924            5 :     DevType devType = HrtGetDeviceType();
     925           10 :     if (devType == DevType::DEV_TYPE_910A2 || devType == DevType::DEV_TYPE_910A3 || devType == DevType::DEV_TYPE_950
     926           10 :         || devType == DevType::DEV_TYPE_960) {
     927            4 :         return;
     928              :     }
     929              :     // 910A芯片限制超时时长为68的倍数
     930            1 :     s32 intPart = timeOut / HCCL_INTEVAL_EXEC_TIME_OUT_S;
     931            1 :     intPart = (intPart == 0) ? 1 : intPart;
     932            1 :     timeOut = intPart * HCCL_INTEVAL_EXEC_TIME_OUT_S;
     933              : }
     934              : 
     935           12 : void ProcRdmaTimeout(u32& timeout)
     936              : {
     937              :     // HCCL_RDMA_TIMEOUT 合法范围为:[0, 31],超出31按照0进行处理,表示永不超时
     938           12 :     if (timeout > EnvRdmaConfig::HCCL_RDMA_TIMEOUT_MAX) {
     939            9 :         HCCL_WARNING(
     940              :             "HCCL_RDMA_TIMEOUT[%u] exceeds max [%u], reset to [%u]", timeout, EnvRdmaConfig::HCCL_RDMA_TIMEOUT_MAX,
     941              :             EnvRdmaConfig::HCCL_RDMA_TIMEOUT_MIN);
     942            3 :         timeout = EnvRdmaConfig::HCCL_RDMA_TIMEOUT_MIN;
     943              :     }
     944           12 : }
     945              : 
     946              : /*-------------------------- detour type -------------------------*/
     947              : // 临时方案,特定场景执行算法会报错,后续适配了再放开
     948            6 : HcclDetourType CastDetourType(const std::string& s)
     949              : {
     950            6 :     if (s == "detour:1") {
     951            6 :         HCCL_INFO("HCCL detour type is 2P (detour:1).");
     952            2 :         return HcclDetourType::HCCL_DETOUR_ENABLE_2P;
     953            4 :     } else if (s == "detour:0") {
     954            3 :         HCCL_INFO("HCCL detour type is disable (detour:0).");
     955              :     } else {
     956            3 :         THROW<NotSupportException>(StringFormat("environment variable HCCL_DETOUR currently only supports"
     957              :                                                 " detour:1 and detour:0 or not set."));
     958              :     }
     959            1 :     return HcclDetourType::HCCL_DETOUR_DISABLE;
     960              : }
     961              : 
     962              : /*----------------------- multi qp src port config --------------------------*/
     963              : std::vector<std::uint16_t>
     964            3 : GetMultiQpSrcPortsByIpPair(const MultiQpSrcPortConfig& config, const IpAddress& srcIp, const IpAddress& dstIp)
     965              : {
     966            3 :     if (!config.IsAvailable()) {
     967            0 :         return {};
     968              :     }
     969              : 
     970            3 :     std::string srcIpStr = srcIp.GetIpStr();
     971            3 :     std::string dstIpStr = dstIp.GetIpStr();
     972            3 :     bool isIpv4 = (srcIp.GetFamily() == AF_INET);
     973              : 
     974            3 :     std::string key = srcIpStr + "," + dstIpStr;
     975            3 :     auto it = config.ipPairToPorts.find(key);
     976            3 :     if (it != config.ipPairToPorts.end()) {
     977            1 :         return it->second;
     978              :     }
     979              : 
     980            2 :     key = (isIpv4 ? "0.0.0.0," : "::,") + dstIpStr;
     981            2 :     it = config.ipPairToPorts.find(key);
     982            2 :     if (it != config.ipPairToPorts.end()) {
     983            0 :         return it->second;
     984              :     }
     985              : 
     986            2 :     key = srcIpStr + (isIpv4 ? ",0.0.0.0" : ",::");
     987            2 :     it = config.ipPairToPorts.find(key);
     988            2 :     if (it != config.ipPairToPorts.end()) {
     989            0 :         return it->second;
     990              :     }
     991              : 
     992            2 :     key = isIpv4 ? "0.0.0.0,0.0.0.0" : "::,::";
     993            2 :     it = config.ipPairToPorts.find(key);
     994            2 :     if (it != config.ipPairToPorts.end()) {
     995            0 :         return it->second;
     996              :     }
     997              : 
     998            2 :     return {};
     999            3 : }
    1000              : 
    1001            0 : u32 GetMultiQpPortsNumByIpPair(const MultiQpSrcPortConfig& config, const IpAddress& srcIp, const IpAddress& dstIp)
    1002              : {
    1003            0 :     auto ports = GetMultiQpSrcPortsByIpPair(config, srcIp, dstIp);
    1004            0 :     return static_cast<u32>(ports.size());
    1005            0 : }
    1006              : 
    1007              : } // namespace Hccl
        

Generated by: LCOV version 2.0-1