LCOV - code coverage report
Current view: top level - legacy/ascend950/framework/topo/rank_info_detect - bootstrap_ip.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.5 % 130 119
Test Date: 2026-08-04 10:52:23 Functions: 100.0 % 11 11

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

Generated by: LCOV version 2.0-1