LCOV - code coverage report
Current view: top level - coll_communicator_mgr/rank_info_detect - bootstrap_ip.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.8 % 130 109
Test Date: 2026-08-18 17:47:01 Functions: 90.9 % 11 10

            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 "bootstrap_ip.h"
      12              : #include <mutex>
      13              : #include <algorithm>
      14              : #include "whitelist.h"
      15              : #include "env_config/env_config_v2.h"
      16              : #include "exception_util.h"
      17              : #include "adapter_error_manager_pub.h"
      18              : 
      19              : namespace Hccl {
      20              : 
      21              : static UniversalConcurrentMap<u32, IpAddress> bootstrapIps; // <devPhyId, ip>
      22              : 
      23            0 : std::vector<IpAddress> GetHostSocketWhitelist()
      24              : {
      25            0 :     std::vector<IpAddress> hostSocketWhitelist{};
      26              : 
      27              :     // 文件路径在g_externalInput.hcclWhiteList已经做过合法性判断, 无需再次校验
      28            0 :     std::string fileName = EnvConfig::GetInstance().GetHostNicConfig().GetWhiteListFile();
      29            0 :     CHK_PRT_THROW(
      30              :         fileName.empty(),
      31              :         HCCL_ERROR(
      32              :             "[%s] HCCL_WHITELIST_DISABLE variable is [0],but "
      33              :             "HCCL_WHITELIST_FILE is not set",
      34              :             __func__),
      35              :         InternalException, "whiteList file name empty");
      36              : 
      37            0 :     Whitelist::GetInstance().LoadConfigFile(fileName);
      38            0 :     Whitelist::GetInstance().GetHostWhiteList(hostSocketWhitelist);
      39            0 :     CHK_PRT_THROW(
      40              :         hostSocketWhitelist.empty(),
      41              :         HCCL_ERROR("[%s] whitelist file[%s] have no valid host ip.", __func__, fileName.c_str()), InternalException,
      42              :         "whiteList invalid");
      43              : 
      44            0 :     HCCL_INFO(
      45              :         "[%s] get host socket whitelist success. there are %zu host ip in the whitelist.", __func__,
      46              :         hostSocketWhitelist.size());
      47            0 :     return hostSocketWhitelist;
      48            0 : }
      49              : 
      50            8 : void GetAllValidHostIfInfos(
      51              :     const std::vector<std::pair<std::string, IpAddress>>& hostIfInfos,
      52              :     vector<std::pair<std::string, IpAddress>>& ifInfos)
      53              : {
      54            8 :     if (!EnvConfig::GetInstance().GetHostNicConfig().GetWhitelistDisable()) {
      55            5 :         auto whitelist = GetHostSocketWhitelist();
      56           10 :         for (auto& ifInfo : hostIfInfos) {
      57            5 :             auto iter = find(whitelist.begin(), whitelist.end(), ifInfo.second);
      58            5 :             if (iter != whitelist.end()) {
      59            4 :                 ifInfos.push_back({ifInfo.first, ifInfo.second});
      60              :             }
      61              :         }
      62            5 :     } else {
      63            3 :         ifInfos = hostIfInfos;
      64              :     }
      65            8 : }
      66              : 
      67            1 : bool FindHostIpbyControlIfIp(const std::vector<std::pair<std::string, IpAddress>>& hostIfInfos, IpAddress& ipAddress)
      68              : {
      69              :     // 匹配指定IP的网卡信息
      70            1 :     auto it = std::find_if(hostIfInfos.begin(), hostIfInfos.end(), [&ipAddress](const auto& hostIfInfo) {
      71            1 :         return hostIfInfo.second == ipAddress;
      72              :     });
      73            1 :     if (it != hostIfInfos.end()) {
      74            1 :         HCCL_INFO(
      75              :             "[%s] find hostIp success, name[%s] ip[%s]", __func__, it->first.c_str(), ipAddress.GetIpStr().c_str());
      76            1 :         return true;
      77              :     }
      78            0 :     RPT_INPUT_ERR(
      79              :         true, "EI0001", std::vector<std::string>({"value", "env", "expect"}),
      80              :         std::vector<std::string>(
      81              :             {ipAddress.GetIpStr(), "HCCL_IF_IP", "a valid IP from the available network interfaces"}));
      82            0 :     HCCL_ERROR(
      83              :         "[%s] Env config \"HCCL_IF_IP\" is [%s] which is not found in the nic list.", __func__,
      84              :         ipAddress.GetIpStr().c_str());
      85            0 :     return false;
      86            0 : }
      87              : 
      88            3 : bool FindHostIpByIfName(
      89              :     const std::vector<std::pair<std::string, IpAddress>>& hostIfInfos, s32 family, IpAddress& ipAddress)
      90              : {
      91            3 :     HCCL_INFO("[%s] find host ip start. family[%d]", __func__, family);
      92              : 
      93              :     // 使用Host网卡名和环境变量HCCL_SOCKET_IFNAME配置的网卡名进行比较
      94            3 :     auto socketIfName = EnvConfig::GetInstance().GetHostNicConfig().GetSocketIfName();
      95            5 :     for (auto& hostIfInfo : hostIfInfos) {
      96            3 :         if (hostIfInfo.second.GetFamily() != family) {
      97            1 :             continue;
      98              :         }
      99            2 :         u32 matchLen = hostIfInfo.first.size();
     100            2 :         bool configIfNamesFlag = false;
     101            4 :         for (u32 i = 0; i < socketIfName.configIfNames.size(); i++) {
     102            2 :             matchLen = socketIfName.searchExact ? hostIfInfo.first.size() : socketIfName.configIfNames[i].size();
     103            2 :             if (hostIfInfo.first.compare(0, matchLen, socketIfName.configIfNames[i], 0, matchLen) == 0) {
     104            1 :                 configIfNamesFlag = true;
     105              :             }
     106              :         }
     107            2 :         if (configIfNamesFlag != socketIfName.searchNot) {
     108            1 :             configIfNamesFlag = false;
     109            1 :             ipAddress = hostIfInfo.second;
     110            1 :             HCCL_INFO(
     111              :                 "[%s] find hostIp success by ifName. name[%s] ip[%s]", __func__, hostIfInfo.first.c_str(),
     112              :                 hostIfInfo.second.GetIpStr().c_str());
     113            1 :             return true;
     114              :         }
     115              :     }
     116              : 
     117            2 :     HCCL_WARNING("[%s] find host ip fail by family[%d] ifName.", __func__, family);
     118            2 :     return false;
     119            3 : }
     120              : 
     121            2 : bool FindHostIpByIfName(const std::vector<std::pair<std::string, IpAddress>>& hostIfInfos, IpAddress& ipAddress)
     122              : {
     123            2 :     s32 socketFamily = EnvConfig::GetInstance().GetSocketConfig().GetSocketFamily();
     124            2 :     socketFamily = (socketFamily == -1) ? AF_INET : socketFamily;
     125            2 :     bool ret = FindHostIpByIfName(hostIfInfos, socketFamily, ipAddress);
     126            2 :     if (!ret) {
     127            1 :         socketFamily = (socketFamily == AF_INET) ? AF_INET6 : AF_INET;
     128            1 :         ret = FindHostIpByIfName(hostIfInfos, socketFamily, ipAddress);
     129              :     }
     130            2 :     return ret;
     131              : }
     132              : 
     133            9 : bool FindHostIpFromOneNicClass(
     134              :     const std::map<std::string, std::map<std::string, IpAddress>>& nicClassifyInfo, const std::string& nicClass,
     135              :     IpAddress& ip)
     136              : {
     137            9 :     auto iterClass = nicClassifyInfo.find(nicClass);
     138            9 :     if (iterClass != nicClassifyInfo.end()) {
     139            4 :         if (iterClass->second.empty()) {
     140            0 :             HCCL_WARNING("[%s] nic class[%s]: no valid ip.", __func__, nicClass.c_str());
     141            0 :             return false;
     142              :         }
     143            4 :         ip = iterClass->second.begin()->second;
     144            4 :         HCCL_INFO(
     145              :             "[%s] find host ip success by nic class[%s]. host ifName[%s] ip[%s]", __func__, nicClass.c_str(),
     146              :             iterClass->second.begin()->first.c_str(), ip.GetIpStr().c_str());
     147            4 :         return true;
     148              :     }
     149            5 :     return false;
     150              : }
     151              : 
     152            4 : bool FindHostIPByNicClass(
     153              :     const std::vector<std::pair<std::string, IpAddress>>& hostIfInfos, s32 family, IpAddress& ipAddress)
     154              : {
     155            4 :     std::map<std::string, std::map<std::string, IpAddress>> nicClassify;
     156            8 :     for (auto& hostIfInfo : hostIfInfos) {
     157            4 :         if (hostIfInfo.second.GetFamily() != family) {
     158            0 :             continue;
     159              :         }
     160            4 :         if (hostIfInfo.first.find("lo") == 0) {
     161            4 :             nicClassify["lo"].insert({hostIfInfo.first, hostIfInfo.second});
     162            2 :         } else if (hostIfInfo.first.find("docker") == 0) {
     163            2 :             nicClassify["docker"].insert({hostIfInfo.first, hostIfInfo.second});
     164              :         } else {
     165            2 :             nicClassify["normal"].insert({hostIfInfo.first, hostIfInfo.second});
     166              :         }
     167            4 :         HCCL_DEBUG(
     168              :             "[%s] ifName[%s] addr[%s]", __func__, hostIfInfo.first.c_str(), hostIfInfo.second.GetIpStr().c_str());
     169              :     }
     170              : 
     171            8 :     if (FindHostIpFromOneNicClass(nicClassify, "normal", ipAddress)) {
     172            1 :         HCCL_INFO("[%s] find host ip success by nic class[normal]. ip[%s].", __func__, ipAddress.GetIpStr().c_str());
     173            1 :         return true;
     174            6 :     } else if (FindHostIpFromOneNicClass(nicClassify, "docker", ipAddress)) {
     175            1 :         HCCL_INFO("[%s] find host ip success by nic class[docker]. ip[%s].", __func__, ipAddress.GetIpStr().c_str());
     176            1 :         return true;
     177            4 :     } else if (FindHostIpFromOneNicClass(nicClassify, "lo", ipAddress)) {
     178            2 :         HCCL_INFO("[%s] find host ip success by nic class[lo]. ip[%s].", __func__, ipAddress.GetIpStr().c_str());
     179            2 :         return true;
     180              :     }
     181              : 
     182            0 :     HCCL_WARNING("[%s] find hostIp by nic class[normal_docket_lo] fail.", __func__);
     183            0 :     return false;
     184            4 : }
     185              : 
     186            4 : bool FindHostIPByNicClass(const std::vector<std::pair<std::string, IpAddress>>& hostIfInfos, IpAddress& ipAddress)
     187              : {
     188            4 :     s32 socketFamily = EnvConfig::GetInstance().GetSocketConfig().GetSocketFamily();
     189            4 :     socketFamily = (socketFamily == -1) ? AF_INET : socketFamily;
     190            4 :     bool ret = FindHostIPByNicClass(hostIfInfos, socketFamily, ipAddress);
     191            4 :     if (!ret) {
     192            0 :         socketFamily = (socketFamily == AF_INET) ? AF_INET6 : AF_INET;
     193            0 :         ret = FindHostIPByNicClass(hostIfInfos, socketFamily, ipAddress);
     194              :     }
     195            4 :     return ret;
     196              : }
     197              : 
     198            7 : bool FindLocalHostIp(const std::vector<std::pair<std::string, IpAddress>>& hostIfInfos, IpAddress& ipAddress)
     199              : {
     200              :     // 根据HCCL_IF_IP查询ips中匹配的LocalHostIP
     201            7 :     ipAddress = EnvConfig::GetInstance().GetHostNicConfig().GetControlIfIp();
     202            7 :     if (!ipAddress.IsInvalid()) {
     203            1 :         return FindHostIpbyControlIfIp(hostIfInfos, ipAddress);
     204              :     }
     205              : 
     206              :     // 根据HCCL_SOCKET_IFNAME查询ips中匹配的LocalHostIP
     207            6 :     auto ifnames = EnvConfig::GetInstance().GetHostNicConfig().GetSocketIfName();
     208            6 :     if (!ifnames.configIfNames.empty()) {
     209            2 :         bool ret = FindHostIpByIfName(hostIfInfos, ipAddress);
     210            2 :         if (!ret) {
     211           14 :             RPT_INPUT_ERR(
     212              :                 true, "EI0001", std::vector<std::string>({"value", "env", "expect"}),
     213              :                 std::vector<std::string>(
     214              :                     {ifnames.configIfNameStr, "HCCL_SOCKET_IFNAME",
     215              :                      "a valid network interface name from the available interfaces"}));
     216            1 :             HCCL_ERROR(
     217              :                 "[Init][EnvVarParam][%s] Env config \"HCCL_SOCKET_IFNAME\" is [%s] which is not found in the nic list",
     218              :                 __func__, ifnames.configIfNameStr.c_str());
     219            2 :             for (auto& ifInfo : hostIfInfos) {
     220            1 :                 HCCL_ERROR(
     221              :                     "[%s] get host ip fail by socket Ifname. nic name[%s] ip[%s]", __func__, ifInfo.first.c_str(),
     222              :                     ifInfo.second.Describe().c_str());
     223              :             }
     224              :         }
     225            2 :         return ret;
     226              :     }
     227              : 
     228              :     // 不匹配的话以此类推选择normal/docker/lo类型的
     229            4 :     return FindHostIPByNicClass(hostIfInfos, ipAddress);
     230            8 : }
     231              : 
     232           12 : const IpAddress& GetBootstrapIp(u32 devPhyId)
     233              : {
     234              :     // 如果已获取过则直接使用ip
     235           12 :     auto it = bootstrapIps.Find(devPhyId);
     236           12 :     if (it.second) {
     237            2 :         CHK_PRT_RET(
     238              :             !it.first->second.IsInvalid(),
     239              :             HCCL_INFO("[%s] hostIp[%s] already exists.", __func__, it.first->second.GetIpStr().c_str()),
     240              :             it.first->second);
     241              :     }
     242              : 
     243              :     // 获取网卡ip
     244           10 :     auto hostIfInfos = HrtGetHostIf(devPhyId);
     245           14 :     CHK_PRT_THROW(
     246              :         hostIfInfos.empty(), HCCL_ERROR("[%s] there is no host if.", __func__), InternalException, "get host ip error");
     247              : 
     248              :     // 若白名单使能则过滤
     249            8 :     vector<std::pair<std::string, IpAddress>> ifInfos;
     250            8 :     GetAllValidHostIfInfos(hostIfInfos, ifInfos);
     251           10 :     CHK_PRT_THROW(
     252              :         ifInfos.empty(), HCCL_ERROR("[%s] there is no valid host if in whitelist.", __func__), InternalException,
     253              :         "get host ip error");
     254              : 
     255              :     // 获得有效的bootstrapIp
     256            7 :     IpAddress ipAddress{};
     257            7 :     bool ret = FindLocalHostIp(ifInfos, ipAddress);
     258            9 :     CHK_PRT_THROW(!ret, HCCL_ERROR("[%s] there is no valid host ip.", __func__), InternalException, "no valid host ip");
     259              : 
     260              :     // 保存有效的bootstrapIp且返回
     261            6 :     bootstrapIps[devPhyId] = ipAddress;
     262              : 
     263            6 :     HCCL_INFO("[%s] get hostIp success. ipAddress[%s]", __func__, ipAddress.GetIpStr().c_str());
     264            6 :     return bootstrapIps[devPhyId];
     265           12 : }
     266              : 
     267              : } // namespace Hccl
        

Generated by: LCOV version 2.0-1