LCOV - code coverage report
Current view: top level - legacy/ascend950/framework/topo/new_topo_builder/phy_topo_builder - phy_topo_builder.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.1 % 160 149
Test Date: 2026-08-04 10:52:23 Functions: 100.0 % 13 13

            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 "phy_topo_builder.h"
      12              : #include "log.h"
      13              : #include "json_parser.h"
      14              : #include "exception_util.h"
      15              : #include "null_ptr_exception.h"
      16              : #include "invalid_params_exception.h"
      17              : #include "adapter_error_manager_pub.h"
      18              : 
      19              : namespace Hccl {
      20              : 
      21           57 : PhyTopoBuilder &PhyTopoBuilder::GetInstance()
      22              : {
      23           57 :     static PhyTopoBuilder phyTopoBuilder;
      24           57 :     return phyTopoBuilder;
      25              : }
      26              : 
      27              : // 根据nodeType和localId创建节点
      28          150 : std::shared_ptr<PhyTopo::Node> CreateNode(const PhyTopo::Node::NodeType nodeType, const LocalId localId)
      29              : {
      30          150 :     if (nodeType == PhyTopo::Node::NodeType::PEER) {
      31          125 :         return std::make_shared<PhyTopo::Peer>(localId);
      32              :     } else {
      33           25 :         return std::make_shared<PhyTopo::Fabric>();
      34              :     }
      35              : }
      36              : 
      37           30 : void PhyTopoBuilder::Build(const std::string &topoPath)
      38              : {
      39           30 :     std::lock_guard<std::mutex> lock(phyTopoMutex);
      40              :     
      41           30 :     if (PhyTopo::GetInstance()->IsInitFinished()) {
      42           36 :         HCCL_INFO("PhyTopo has been initialized and does not need to be rebuilt");
      43           12 :         return;
      44              :     }
      45              : 
      46           18 :     if (topoPath.empty()) {
      47            1 :         RPT_INPUT_ERR(true, "EI0004", std::vector<std::string>({"ranktable_path", "error_reason"}),
      48              :                       std::vector<std::string>({"Please check the path configuration of the topo json file.",
      49              :                      "The rankTable file path does not exist, the permission is insufficient, or the JSON format is incorrect."
      50              :                       }));
      51            1 :         THROW<InvalidParamsException>("[PhyTopoBuilder::%s] Topo path is empty.", __func__);
      52              :     }
      53              : 
      54           51 :     HCCL_DEBUG("[PhyTopoBuilder::%s]Start to build physic topo.", __func__);
      55              : 
      56           17 :     auto topoInfo = LoadTopoInfo(topoPath);
      57              :     // 根据topoInfo,按netLayer构造Graph
      58           47 :     for (const auto &iter : topoInfo->edges) {
      59           30 :         auto netLayer = iter.first;
      60           30 :         auto graph = CreateGraph(iter.second);
      61           30 :         PhyTopo::GetInstance()->AddTopoGraph(netLayer, graph);
      62           90 :         HCCL_DEBUG("[PhyTopoBuilder::%s]Build netLayer[%u] topo graph success.", __func__, netLayer);
      63           30 :     }
      64              : 
      65              :     // 遍历peerList,把peerList中的localId构造peer节点,加到layer-0的graph中
      66           17 :     auto graph = PhyTopo::GetInstance()->GetTopoGraph(0);
      67           17 :     if (graph == nullptr) {
      68            3 :         HCCL_INFO("[PhyTopoBuilder::%s] layer0 graph is nullptr, build now", __func__);
      69            1 :         graph = make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>();
      70            1 :         PhyTopo::GetInstance()->AddTopoGraph(0, graph);
      71              :     }
      72           69 :     for (const auto &iter : topoInfo->peers) {
      73              :         // 判断当前layer0的graph有没有这个节点
      74           52 :         if (!graph->HasNode(iter.localId)) {
      75            1 :             auto node = CreateNode(PhyTopo::Node::NodeType::PEER, iter.localId);
      76            1 :             graph->AddNode(iter.localId, node);
      77            1 :         }
      78              :     }
      79              : 
      80           17 :     PhyTopo::GetInstance()->InitFinish();
      81              : 
      82           51 :     HCCL_DEBUG("[PhyTopoBuilder::%s]build physic topo success.", __func__);
      83           17 :     PhyTopo::GetInstance()->Dump();
      84           30 : }
      85              : 
      86           20 : std::shared_ptr<TopoInfo> PhyTopoBuilder::LoadTopoInfo(const std::string &topoPath)
      87              : {
      88           20 :     std::shared_ptr<TopoInfo> topoInfo = std::make_shared<TopoInfo>();
      89              :     // 检查是否为非法路径以及size的大小。
      90              :     struct stat fileStat;
      91           20 :     if (stat(topoPath.c_str(), &fileStat) != 0) {
      92            9 :         HCCL_ERROR("[PhyTopoBuilder][LoadTopoInfo] Get file stat failed, file path:%s, errno:%d, error: %s",
      93              :                     topoPath.c_str(), errno, strerror(errno));
      94            3 :         THROW<InvalidParamsException>("[PhyTopoBuilder][LoadTopoInfo]Get file stat failed, file path:%s, errno:%d, error: %s",
      95            3 :                                             topoPath.c_str(), errno, strerror(errno));
      96              :     }
      97              : 
      98           17 :     u64 topoFileSize = static_cast<u64>(fileStat.st_size);
      99           17 :     if (topoFileSize > SUPPORT_MAX_TOPOFILE_SIZE || topoFileSize <= 0) {
     100            0 :         HCCL_ERROR("[PhyTopoBuilder][LoadTopoInfo] topoFileSize size: %llu, topoFile must be greater than 0 and less than %u", topoFileSize, SUPPORT_MAX_TOPOFILE_SIZE);
     101            0 :         THROW<InvalidParamsException>(StringFormat(
     102              :             "[PhyTopoBuilder][LoadTopoInfo]file %s size (%llu bytes) exceeds max allowed size (%u bytes)",
     103              :              topoPath.c_str(), topoFileSize, SUPPORT_MAX_TOPOFILE_SIZE));
     104              :     }
     105              :     
     106              :     JsonParser                topoParser;
     107           17 :     topoParser.ParseFile(topoPath, *topoInfo);
     108           17 :     topoInfo_ = topoInfo;
     109           17 :     return topoInfo;
     110            3 : }
     111              : 
     112          116 : shared_ptr<PhyTopo::Link> CreatePeer2PeerLink(const LinkParams &params)
     113              : {
     114          116 :     LinkType linkType = LinkType::PEER2PEER;
     115              :     auto srcIface =
     116          116 :         std::make_shared<PhyTopo::ConnInterface>(params.localAPorts, params.position, linkType, params.protocols);
     117              :     auto dstIface =
     118          116 :         std::make_shared<PhyTopo::ConnInterface>(params.localBPorts, params.position, linkType, params.protocols);
     119          116 :     PhyTopo::LinkAttributes linkAttrs;
     120          116 :     linkAttrs.linktype = linkType;
     121          116 :     linkAttrs.protocols = params.protocols;
     122              :     auto link = std::make_shared<PhyTopo::Link>(
     123          116 :         params.srcNode, params.dstNode, linkAttrs, params.topoType, params.topoInstanceId);
     124          116 :     link->SetSourceIface(srcIface);
     125          116 :     params.srcNode->AddConnInterface(srcIface);
     126          116 :     link->SetTargetIface(dstIface);
     127          116 :     params.dstNode->AddConnInterface(dstIface);
     128          232 :     return {link};
     129          116 : }
     130              : 
     131              : 
     132          336 : shared_ptr<PhyTopo::Link> CreatePeer2NetLink(const LinkParams &params)
     133              : {
     134          336 :     LinkType linkType = LinkType::PEER2NET;
     135          336 :     auto srcIface = std::make_shared<PhyTopo::ConnInterface>(params.localAPorts, params.position, linkType, params.protocols);
     136              :     // fabric 没有ports
     137          336 :     std::set<std::string> ports{};
     138          336 :     auto dstIface =std::make_shared<PhyTopo::ConnInterface>(ports, params.position, linkType, params.protocols);
     139          336 :     PhyTopo::LinkAttributes linkAttrs;
     140          336 :     linkAttrs.linktype = linkType;
     141          336 :     linkAttrs.protocols = params.protocols;
     142              :     auto link = std::make_shared<PhyTopo::Link>(
     143          336 :         params.srcNode, params.dstNode, linkAttrs, params.topoType, params.topoInstanceId);
     144          336 :     link->SetSourceIface(srcIface);
     145          336 :     params.srcNode->AddConnInterface(srcIface);
     146          336 :     link->SetTargetIface(dstIface);
     147          336 :     params.dstNode->AddConnInterface(dstIface);
     148          672 :     return {link};
     149          336 : }
     150              : 
     151              : // 根据链路类型建链
     152          452 : shared_ptr<PhyTopo::Link> CreateLink(const LinkType linkType, const LinkParams &params)
     153              : {
     154          452 :     if (linkType == LinkType::PEER2PEER) {
     155          116 :         return CreatePeer2PeerLink(params);
     156              :     } else {
     157          336 :         return CreatePeer2NetLink(params);
     158              :     }
     159              : }
     160              : 
     161          452 : NodeId GetNodeId(const PhyTopo::Node::NodeType nodeType, LocalId localId) 
     162              : {
     163          452 :     switch (nodeType) {
     164          284 :         case  PhyTopo::Node::NodeType::PEER:
     165          284 :             return PhyTopo::Peer::GetId(localId);
     166          168 :         case  PhyTopo::Node::NodeType::FABRIC:
     167          168 :             return PhyTopo::Fabric::GetId();
     168            0 :         default:
     169            0 :             THROW<InvalidParamsException>(StringFormat("[PhyTopoBuilder]Invalid NodeType."));
     170              :             return 0;
     171              :     }
     172              : }
     173              : 
     174           37 : std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> PhyTopoBuilder::CreateGraph(
     175              :     const std::vector<EdgeInfo> &edges) const
     176              : {
     177           37 :     auto graph = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>();
     178              : 
     179          263 :     for (const auto &edgeInfo : edges) {
     180          226 :         std::shared_ptr<PhyTopo::Node> nodeA;
     181          226 :         std::shared_ptr<PhyTopo::Node> nodeB;
     182              : 
     183              :         // 生成 nodeAId,localA 始终为 PEER 类型
     184          226 :         NodeId nodeAId = GetNodeId(PhyTopo::Node::NodeType::PEER, edgeInfo.localA);
     185              :         // 获取或创建 nodeA
     186          226 :         if (!graph->HasNode(nodeAId)) {
     187           82 :             nodeA = CreateNode(PhyTopo::Node::NodeType::PEER, edgeInfo.localA);
     188           82 :             graph->AddNode(nodeAId, nodeA);
     189          246 :             HCCL_DEBUG("[PhyTopoBuilder::%s] Add node[%llu] success.", __func__, nodeAId);
     190              :         } else {
     191              :             // 使用 TraverseNode 查找 nodeA
     192          144 :             graph->TraverseNode([&nodeA, nodeAId](NodeId id, const std::shared_ptr<PhyTopo::Node> &n) {
     193          636 :                 if (id == nodeAId) {
     194          144 :                     nodeA = n;
     195              :                 }
     196          636 :             });
     197          144 :             if (nodeA == nullptr) {
     198            0 :                 HCCL_ERROR("[PhyTopoBuilder::CreateGraph] nodeAId [%llu] not found.", nodeAId);
     199            0 :                 THROW<NullPtrException>(
     200            0 :                     StringFormat("[PhyTopoBuilder::CreateGraph] Unable to find node [%llu].", nodeAId));
     201              :             }
     202              :         }
     203              : 
     204              :         // 根据 linkType 生成 nodeBId
     205          226 :         PhyTopo::Node::NodeType nodeBType;
     206          226 :         if (edgeInfo.linkType == LinkType::PEER2PEER) {
     207           58 :             nodeBType = PhyTopo::Node::NodeType::PEER;
     208              :         } else {
     209          168 :             nodeBType = PhyTopo::Node::NodeType::FABRIC;
     210              :         }
     211              : 
     212          226 :         NodeId nodeBId = GetNodeId(nodeBType, edgeInfo.localB);
     213              :         // 获取或创建 nodeB
     214          226 :         if (!graph->HasNode(nodeBId)) {
     215           67 :             nodeB = CreateNode(nodeBType, edgeInfo.localB);
     216           67 :             graph->AddNode(nodeBId, nodeB);
     217          201 :             HCCL_DEBUG("[PhyTopoBuilder::%s] Add node[%llu] success.", __func__, nodeBId);
     218              :         } else {
     219              :             // 使用 TraverseNode 查找 nodeB
     220          159 :             graph->TraverseNode([&nodeB, nodeBId](NodeId id, const std::shared_ptr<PhyTopo::Node> &n) {
     221          746 :                 if (id == nodeBId) {
     222          159 :                     nodeB = n;
     223              :                 }
     224          746 :             });
     225          159 :             if (nodeB == nullptr) {
     226            0 :                 HCCL_ERROR("[PhyTopoBuilder::CreateGraph] nodeBId [%llu] not found.", nodeBId);
     227            0 :                 THROW<NullPtrException>(
     228            0 :                     StringFormat("[PhyTopoBuilder::CreateGraph] Unable to find node [%llu].", nodeBId));
     229              :             }
     230              :         }
     231              : 
     232              :         // 双向分别创建link
     233              :         LinkParams abLinkParams{
     234              :             nodeA,
     235              :             nodeB,
     236          226 :             edgeInfo.localAPorts,
     237          226 :             edgeInfo.localBPorts,
     238              :             edgeInfo.position,
     239              :             edgeInfo.topoType,
     240          226 :             edgeInfo.topoInstId,
     241          226 :             edgeInfo.protocols
     242          226 :         };
     243          226 :         auto abLinks = CreateLink(edgeInfo.linkType, abLinkParams);
     244          226 :         graph->AddEdge(nodeAId, nodeBId, abLinks);
     245              :         LinkParams baLinkParams{
     246              :             nodeB,
     247              :             nodeA,
     248          226 :             edgeInfo.localBPorts,
     249          226 :             edgeInfo.localAPorts,
     250              :             edgeInfo.position,
     251              :             edgeInfo.topoType,
     252          226 :             edgeInfo.topoInstId,
     253          226 :             edgeInfo.protocols
     254          226 :         };
     255          226 :         auto baLinks = CreateLink(edgeInfo.linkType, baLinkParams);
     256          226 :         graph->AddEdge(nodeBId, nodeAId, baLinks);
     257          226 :     }
     258              : 
     259           37 :     return graph;
     260            0 : }
     261              : 
     262              : 
     263            3 : void PhyTopoBuilder::RecoverBuild(const TopoInfo &topoInfo)
     264              : {
     265            3 :     std::lock_guard<std::mutex> lock(phyTopoMutex);
     266              : 
     267              :     // PhyTopo::GetInstance()->ResetInstance();
     268            3 :     if (PhyTopo::GetInstance()->IsInitFinished()) {
     269            1 :         return;
     270              :     }
     271              :     // 根据topoInfo,按netLayer构造Graph
     272            6 :     for (const auto &iter : topoInfo.edges) {
     273            4 :         auto netLayer = iter.first;
     274            4 :         auto graph = CreateGraph(iter.second);
     275            4 :         PhyTopo::GetInstance()->AddTopoGraph(netLayer, graph);
     276           12 :         HCCL_DEBUG("[PhyTopoBuilder::%s]Build netLayer[%u] topo graph success.", __func__, netLayer);
     277            4 :     }
     278              : 
     279            2 :     PhyTopo::GetInstance()->InitFinish();
     280              : 
     281            6 :     HCCL_DEBUG("[PhyTopoBuilder::%s]build physic topo success.", __func__);
     282            2 :     PhyTopo::GetInstance()->Dump();
     283            3 : }
     284              : 
     285           23 : std::shared_ptr<TopoInfo> PhyTopoBuilder::GetTopoInfo() const
     286              : {
     287           23 :     return topoInfo_;
     288              : }
     289              : 
     290              : } // namespace Hccl
        

Generated by: LCOV version 2.0-1