| @@ -25,54 +25,42 @@ bool PhyTopo::IsInitFinished() const { return initFlag; } | |||
| 25 | 25 | ||
| 26 | void PhyTopo::Clear() | 26 | void PhyTopo::Clear() |
| 27 | { | 27 | { |
| 28 | - topos.clear(); | 28 | + topo_.reset(); |
| 29 | initFlag = false; | 29 | initFlag = false; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | -void PhyTopo::AddTopoGraph(const u32 netLayer, std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo) | 32 | +void PhyTopo::AddTopoGraph(std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo) |
| 33 | { | 33 | { |
| 34 | if (!initFlag) { | 34 | if (!initFlag) { |
| 35 | - topos[netLayer] = topo; | 35 | + // 物理拓扑只保存一张无逻辑层级的图。 |
| 36 | - HCCL_DEBUG("[PhyTopo]add topo success, netLayer [%u], topo size is [%zu]", netLayer, topos.size()); | 36 | + topo_ = topo; |
| 37 | + HCCL_DEBUG("[PhyTopo] add physical topo graph success."); | ||
| 37 | } else { | 38 | } else { |
| 38 | THROW<InternalException>("PhyTopo AddTopoGraph fail. PhyTopo has been initialized " | 39 | THROW<InternalException>("PhyTopo AddTopoGraph fail. PhyTopo has been initialized " |
| 39 | "and cannot be changed, please check."); | 40 | "and cannot be changed, please check."); |
| 40 | } | 41 | } |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | -std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> PhyTopo::GetTopoGraph(const u32 netLayer) const | 44 | +std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> PhyTopo::GetTopoGraph() const { return topo_; } |
| 44 | -{ | ||
| 45 | - if (topos.find(netLayer) == topos.end()) { | ||
| 46 | - return nullptr; | ||
| 47 | - } | ||
| 48 | - return topos.at(netLayer); | ||
| 49 | -} | ||
| 50 | - | ||
| 51 | -bool PhyTopo::IsNetLayerExisted(const u32 netLayer) const | ||
| 52 | -{ | ||
| 53 | - if (topos.find(netLayer) == topos.end()) { | ||
| 54 | - return false; | ||
| 55 | - } | ||
| 56 | - return true; | ||
| 57 | -} | ||
| 58 | 45 | ||
| 59 | void PhyTopo::Dump() const | 46 | void PhyTopo::Dump() const |
| 60 | { | 47 | { |
| 61 | HCCL_DEBUG("PhyTopo Dump:"); | 48 | HCCL_DEBUG("PhyTopo Dump:"); |
| 62 | - for (auto& pair : topos) { | 49 | + if (topo_ == nullptr) { |
| 63 | - HCCL_DEBUG("netLayer[%u]:", pair.first); | 50 | + HCCL_DEBUG("physical topo graph is nullptr."); |
| 64 | - HCCL_DEBUG("nodes:"); | 51 | + return; |
| 65 | - std::set<NodeId> nodeIds{}; | 52 | + } |
| 66 | - pair.second->TraverseNode([&](NodeId nodeId, std::shared_ptr<PhyTopo::Node> node) { | 53 | + HCCL_DEBUG("nodes:"); |
| 67 | - nodeIds.insert(nodeId); | 54 | + std::set<NodeId> nodeIds{}; |
| 68 | - HCCL_DEBUG("%s", node->Describe().c_str()); | 55 | + topo_->TraverseNode([&](NodeId nodeId, std::shared_ptr<PhyTopo::Node> node) { |
| 56 | + nodeIds.insert(nodeId); | ||
| 57 | + HCCL_DEBUG("%s", node->Describe().c_str()); | ||
| 58 | + }); | ||
| 59 | + HCCL_DEBUG("links:"); | ||
| 60 | + for (NodeId nodeId : nodeIds) { | ||
| 61 | + topo_->TraverseEdge(nodeId, [&](std::shared_ptr<Link> link) { | ||
| 62 | + HCCL_DEBUG("%s", link->Describe().c_str()); | ||
| 69 | }); | 63 | }); |
| 70 | - HCCL_DEBUG("links:"); | ||
| 71 | - for (NodeId nodeId : nodeIds) { | ||
| 72 | - pair.second->TraverseEdge(nodeId, [&](std::shared_ptr<Link> link) { | ||
| 73 | - HCCL_DEBUG("%s", link->Describe().c_str()); | ||
| 74 | - }); | ||
| 75 | - } | ||
| 76 | } | 64 | } |
| 77 | } | 65 | } |
| 78 | 66 | ||
| @@ -13,7 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | - | ||
| 17 | 16 | ||
| 18 | 17 | ||
| 19 | 18 | ||
| @@ -116,16 +115,15 @@ public: | |||
| 116 | u32 hop{1}; | 115 | u32 hop{1}; |
| 117 | }; | 116 | }; |
| 118 | 117 | ||
| 119 | - void AddTopoGraph(const u32 netLayer, std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo); | 118 | + void AddTopoGraph(std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo); |
| 120 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> GetTopoGraph(const u32 netLayer) const; | 119 | + std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> GetTopoGraph() const; |
| 121 | void InitFinish(); | 120 | void InitFinish(); |
| 122 | bool IsInitFinished() const; | 121 | bool IsInitFinished() const; |
| 123 | void Clear(); | 122 | void Clear(); |
| 124 | void Dump() const; | 123 | void Dump() const; |
| 125 | - bool IsNetLayerExisted(const u32 netLayer) const; | ||
| 126 | 124 | ||
| 127 | private: | 125 | private: |
| 128 | - std::unordered_map<u32, std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>>> topos; | 126 | + std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo_{nullptr}; |
| 129 | bool initFlag{false}; | 127 | bool initFlag{false}; |
| 130 | }; | 128 | }; |
| 131 | } // namespace Hccl | 129 | } // namespace Hccl |
| @@ -56,28 +56,7 @@ void PhyTopoBuilder::Build(const std::string& topoPath) | |||
| 56 | HCCL_DEBUG("[PhyTopoBuilder::%s]Start to build physic topo.", __func__); | 56 | HCCL_DEBUG("[PhyTopoBuilder::%s]Start to build physic topo.", __func__); |
| 57 | 57 | ||
| 58 | auto topoInfo = LoadTopoInfo(topoPath); | 58 | auto topoInfo = LoadTopoInfo(topoPath); |
| 59 | - // 根据topoInfo,按netLayer构造Graph | 59 | + BuildPhyTopo(*topoInfo); |
| 60 | - for (const auto& iter : topoInfo->edges) { | ||
| 61 | - auto netLayer = iter.first; | ||
| 62 | - auto graph = CreateGraph(iter.second); | ||
| 63 | - PhyTopo::GetInstance()->AddTopoGraph(netLayer, graph); | ||
| 64 | - HCCL_DEBUG("[PhyTopoBuilder::%s]Build netLayer[%u] topo graph success.", __func__, netLayer); | ||
| 65 | - } | ||
| 66 | - | ||
| 67 | - // 遍历peerList,把peerList中的localId构造peer节点,加到layer-0的graph中 | ||
| 68 | - auto graph = PhyTopo::GetInstance()->GetTopoGraph(0); | ||
| 69 | - if (graph == nullptr) { | ||
| 70 | - HCCL_INFO("[PhyTopoBuilder::%s] layer0 graph is nullptr, build now", __func__); | ||
| 71 | - graph = make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | ||
| 72 | - PhyTopo::GetInstance()->AddTopoGraph(0, graph); | ||
| 73 | - } | ||
| 74 | - for (const auto& iter : topoInfo->peers) { | ||
| 75 | - // 判断当前layer0的graph有没有这个节点 | ||
| 76 | - if (!graph->HasNode(iter.localId)) { | ||
| 77 | - auto node = CreateNode(PhyTopo::Node::NodeType::PEER, iter.localId); | ||
| 78 | - graph->AddNode(iter.localId, node); | ||
| 79 | - } | ||
| 80 | - } | ||
| 81 | 60 | ||
| 82 | PhyTopo::GetInstance()->InitFinish(); | 61 | PhyTopo::GetInstance()->InitFinish(); |
| 83 | 62 | ||
| @@ -180,6 +159,7 @@ NodeId GetNodeId(const PhyTopo::Node::NodeType nodeType, LocalId localId) | |||
| 180 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> | 159 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> |
| 181 | PhyTopoBuilder::CreateGraph(const std::vector<EdgeInfo>& edges) const | 160 | PhyTopoBuilder::CreateGraph(const std::vector<EdgeInfo>& edges) const |
| 182 | { | 161 | { |
| 162 | + // 所有物理边构建到同一张图,逻辑分层由 RankTable 端口确定。 | ||
| 183 | auto graph = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | 163 | auto graph = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); |
| 184 | 164 | ||
| 185 | for (const auto& edgeInfo : edges) { | 165 | for (const auto& edgeInfo : edges) { |
| @@ -263,6 +243,22 @@ PhyTopoBuilder::CreateGraph(const std::vector<EdgeInfo>& edges) const | |||
| 263 | return graph; | 243 | return graph; |
| 264 | } | 244 | } |
| 265 | 245 | ||
| 246 | +void PhyTopoBuilder::BuildPhyTopo(const TopoInfo& topoInfo) const | ||
| 247 | +{ | ||
| 248 | + // topo.json 只描述物理连接,不再划分逻辑层。 | ||
| 249 | + auto graph = CreateGraph(topoInfo.edges); | ||
| 250 | + // 补齐未出现在 edge_list 中的 Peer 节点。 | ||
| 251 | + for (const auto& peerInfo : topoInfo.peers) { | ||
| 252 | + NodeId nodeId = PhyTopo::Peer::GetId(peerInfo.localId); | ||
| 253 | + if (!graph->HasNode(nodeId)) { | ||
| 254 | + auto node = CreateNode(PhyTopo::Node::NodeType::PEER, peerInfo.localId); | ||
| 255 | + graph->AddNode(nodeId, node); | ||
| 256 | + } | ||
| 257 | + } | ||
| 258 | + PhyTopo::GetInstance()->AddTopoGraph(graph); | ||
| 259 | + HCCL_DEBUG("[PhyTopoBuilder::%s] Build physical topo graph success.", __func__); | ||
| 260 | +} | ||
| 261 | + | ||
| 266 | void PhyTopoBuilder::RecoverBuild(const TopoInfo& topoInfo) | 262 | void PhyTopoBuilder::RecoverBuild(const TopoInfo& topoInfo) |
| 267 | { | 263 | { |
| 268 | std::lock_guard<std::mutex> lock(phyTopoMutex); | 264 | std::lock_guard<std::mutex> lock(phyTopoMutex); |
| @@ -271,13 +267,8 @@ void PhyTopoBuilder::RecoverBuild(const TopoInfo& topoInfo) | |||
| 271 | if (PhyTopo::GetInstance()->IsInitFinished()) { | 267 | if (PhyTopo::GetInstance()->IsInitFinished()) { |
| 272 | return; | 268 | return; |
| 273 | } | 269 | } |
| 274 | - // 根据topoInfo,按netLayer构造Graph | 270 | + topoInfo_ = std::make_shared<TopoInfo>(topoInfo); |
| 275 | - for (const auto& iter : topoInfo.edges) { | 271 | + BuildPhyTopo(topoInfo); |
| 276 | - auto netLayer = iter.first; | ||
| 277 | - auto graph = CreateGraph(iter.second); | ||
| 278 | - PhyTopo::GetInstance()->AddTopoGraph(netLayer, graph); | ||
| 279 | - HCCL_DEBUG("[PhyTopoBuilder::%s]Build netLayer[%u] topo graph success.", __func__, netLayer); | ||
| 280 | - } | ||
| 281 | 272 | ||
| 282 | PhyTopo::GetInstance()->InitFinish(); | 273 | PhyTopo::GetInstance()->InitFinish(); |
| 283 | 274 | ||
| @@ -44,6 +44,7 @@ public: | |||
| 44 | private: | 44 | private: |
| 45 | std::shared_ptr<TopoInfo> LoadTopoInfo(const std::string& topoPath); | 45 | std::shared_ptr<TopoInfo> LoadTopoInfo(const std::string& topoPath); |
| 46 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> CreateGraph(const std::vector<EdgeInfo>& edges) const; | 46 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> CreateGraph(const std::vector<EdgeInfo>& edges) const; |
| 47 | + void BuildPhyTopo(const TopoInfo& topoInfo) const; | ||
| 47 | std::shared_ptr<TopoInfo> topoInfo_; | 48 | std::shared_ptr<TopoInfo> topoInfo_; |
| 48 | std::mutex phyTopoMutex; | 49 | std::mutex phyTopoMutex; |
| 49 | }; | 50 | }; |
| @@ -377,13 +377,13 @@ std::vector<std::shared_ptr<NetInstance::ConnInterface>> NetInstance::Node::GetI | |||
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | void NetInstance::Node::SetEndpointToIface( | 379 | void NetInstance::Node::SetEndpointToIface( |
| 380 | - const CommAddr& commAddr, CommProtocol protocol, const std::shared_ptr<NetInstance::ConnInterface>& iface) | 380 | + u32 netLayer, u32 topoInstId, const CommAddr& commAddr, CommProtocol protocol, |
| 381 | + const std::shared_ptr<NetInstance::ConnInterface>& iface) | ||
| 381 | { | 382 | { |
| 382 | - endpointToIfaceMap_[std::make_pair(commAddr, protocol)] = iface; | 383 | + endpointToIfaceMap_[EndpointKey{netLayer, topoInstId, commAddr, protocol}] = iface; |
| 383 | } | 384 | } |
| 384 | 385 | ||
| 385 | -const std::unordered_map<std::pair<CommAddr, CommProtocol>, std::shared_ptr<NetInstance::ConnInterface>> | 386 | +const NetInstance::Node::EndpointToIfaceMap& NetInstance::Node::GetEndpointToIfaceMap() const |
| 386 | -NetInstance::Node::GetEndpointToIfaceMap() const | ||
| 387 | { | 387 | { |
| 388 | return endpointToIfaceMap_; | 388 | return endpointToIfaceMap_; |
| 389 | } | 389 | } |
| @@ -450,6 +450,17 @@ std::map<std::string, std::vector<IpAddress>> NetInstance::Peer::GetPortAddrMapL | |||
| 450 | return portAddrMapLayer0_; | 450 | return portAddrMapLayer0_; |
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | +bool NetInstance::Peer::TryGetLayer0Address(const std::string& port, IpAddress& addr) const | ||
| 454 | +{ | ||
| 455 | + // 端口归属以 RankTable layer 0 的地址映射为准。 | ||
| 456 | + auto addrIt = portAddrMapLayer0_.find(port); | ||
| 457 | + if (addrIt == portAddrMapLayer0_.end() || addrIt->second.empty()) { | ||
| 458 | + return false; | ||
| 459 | + } | ||
| 460 | + addr = addrIt->second.front(); | ||
| 461 | + return true; | ||
| 462 | +} | ||
| 463 | + | ||
| 453 | PlaneId NetInstance::Fabric::GetPlaneId() const { return planeId_; } | 464 | PlaneId NetInstance::Fabric::GetPlaneId() const { return planeId_; } |
| 454 | 465 | ||
| 455 | NodeId NetInstance::Fabric::GenerateNodeId(FabricId fabricId) const | 466 | NodeId NetInstance::Fabric::GenerateNodeId(FabricId fabricId) const |
| @@ -23,10 +23,72 @@ | |||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | + | ||
| 26 | 27 | ||
| 27 | 28 | ||
| 28 | namespace Hccl { | 29 | namespace Hccl { |
| 29 | constexpr u32 DEFAULT_LISTENING_PORT = 60001; | 30 | constexpr u32 DEFAULT_LISTENING_PORT = 60001; |
| 31 | +// HCCL构建ChannelDesc时会完整复制EndpointLoc,使用其未占用的尾部字节传递拓扑定位信息。 | ||
| 32 | +struct EndpointTopoInfo { | ||
| 33 | + u32 magic; | ||
| 34 | + u32 netLayer; | ||
| 35 | + u32 topoInstId; | ||
| 36 | +}; | ||
| 37 | + | ||
| 38 | +constexpr u32 ENDPOINT_TOPO_INFO_MAGIC = 0x544F504FU; | ||
| 39 | +constexpr size_t ENDPOINT_LOC_RAW_SIZE = sizeof(((EndpointLoc*)nullptr)->raws); | ||
| 40 | +static_assert(ENDPOINT_LOC_RAW_SIZE >= sizeof(EndpointTopoInfo), "EndpointLoc reserved space is insufficient"); | ||
| 41 | +static_assert( | ||
| 42 | + ENDPOINT_LOC_RAW_SIZE - sizeof(EndpointTopoInfo) >= sizeof(((EndpointLoc*)nullptr)->device), | ||
| 43 | + "Endpoint topology info overlaps device location fields"); | ||
| 44 | +constexpr size_t ENDPOINT_TOPO_INFO_OFFSET = ENDPOINT_LOC_RAW_SIZE - sizeof(EndpointTopoInfo); | ||
| 45 | + | ||
| 46 | +inline HcclResult SetEndpointTopoInfo(EndpointDesc& endpointDesc, u32 netLayer, u32 topoInstId) | ||
| 47 | +{ | ||
| 48 | + const EndpointTopoInfo topoInfo{ENDPOINT_TOPO_INFO_MAGIC, netLayer, topoInstId}; | ||
| 49 | + const errno_t ret | ||
| 50 | + = memcpy_s(endpointDesc.loc.raws + ENDPOINT_TOPO_INFO_OFFSET, sizeof(topoInfo), &topoInfo, sizeof(topoInfo)); | ||
| 51 | + return ret == EOK ? HCCL_SUCCESS : HCCL_E_MEMORY; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +inline bool GetEndpointTopoInfo(const EndpointDesc& endpointDesc, u32& netLayer, u32& topoInstId) | ||
| 55 | +{ | ||
| 56 | + EndpointTopoInfo topoInfo{}; | ||
| 57 | + const errno_t ret | ||
| 58 | + = memcpy_s(&topoInfo, sizeof(topoInfo), endpointDesc.loc.raws + ENDPOINT_TOPO_INFO_OFFSET, sizeof(topoInfo)); | ||
| 59 | + if (ret != EOK) { | ||
| 60 | + return false; | ||
| 61 | + } | ||
| 62 | + if (topoInfo.magic != ENDPOINT_TOPO_INFO_MAGIC) { | ||
| 63 | + return false; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + netLayer = topoInfo.netLayer; | ||
| 67 | + topoInstId = topoInfo.topoInstId; | ||
| 68 | + return true; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +// 同一地址和协议可属于不同网络层或拓扑实例,需共同参与Endpoint定位。 | ||
| 72 | +struct EndpointKey { | ||
| 73 | + u32 netLayer; | ||
| 74 | + u32 topoInstId; | ||
| 75 | + CommAddr commAddr; | ||
| 76 | + CommProtocol protocol; | ||
| 77 | + | ||
| 78 | + bool operator==(const EndpointKey& other) const | ||
| 79 | + { | ||
| 80 | + return netLayer == other.netLayer && topoInstId == other.topoInstId && commAddr == other.commAddr | ||
| 81 | + && protocol == other.protocol; | ||
| 82 | + } | ||
| 83 | +}; | ||
| 84 | + | ||
| 85 | +struct EndpointKeyHash { | ||
| 86 | + size_t operator()(const EndpointKey& key) const | ||
| 87 | + { | ||
| 88 | + return std::hash<u32>()(key.netLayer) ^ (std::hash<u32>()(key.topoInstId) << 1) | ||
| 89 | + ^ (std::hash<CommAddr>()(key.commAddr) << 2) ^ (std::hash<CommProtocol>()(key.protocol) << 3); | ||
| 90 | + } | ||
| 91 | +}; | ||
| 30 | class NetInstance { | 92 | class NetInstance { |
| 31 | public: | 93 | public: |
| 32 | class ConnInterface { | 94 | class ConnInterface { |
| @@ -70,6 +132,9 @@ public: | |||
| 70 | 132 | ||
| 71 | class Node { | 133 | class Node { |
| 72 | public: | 134 | public: |
| 135 | + using EndpointToIfaceMap | ||
| 136 | + = std::unordered_map<EndpointKey, std::shared_ptr<NetInstance::ConnInterface>, EndpointKeyHash>; | ||
| 137 | + | ||
| 73 | MAKE_ENUM(NodeType, PEER, FABRIC) | 138 | MAKE_ENUM(NodeType, PEER, FABRIC) |
| 74 | explicit Node(NodeType nodeType) : type_(nodeType) {} | 139 | explicit Node(NodeType nodeType) : type_(nodeType) {} |
| 75 | virtual ~Node() = default; | 140 | virtual ~Node() = default; |
| @@ -80,9 +145,9 @@ public: | |||
| 80 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfacesByLayer(u32 layer) const; | 145 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfacesByLayer(u32 layer) const; |
| 81 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfaces() const; | 146 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfaces() const; |
| 82 | void SetEndpointToIface( | 147 | void SetEndpointToIface( |
| 83 | - const CommAddr& commAddr, CommProtocol protocol, const std::shared_ptr<NetInstance::ConnInterface>& iface); | 148 | + u32 netLayer, u32 topoInstId, const CommAddr& commAddr, CommProtocol protocol, |
| 84 | - const std::unordered_map<std::pair<CommAddr, CommProtocol>, std::shared_ptr<NetInstance::ConnInterface>> | 149 | + const std::shared_ptr<NetInstance::ConnInterface>& iface); |
| 85 | - GetEndpointToIfaceMap() const; | 150 | + const EndpointToIfaceMap& GetEndpointToIfaceMap() const; |
| 86 | NodeId GetNodeId() const; | 151 | NodeId GetNodeId() const; |
| 87 | string GetNodeIdStr() const; | 152 | string GetNodeIdStr() const; |
| 88 | const std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> | 153 | const std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> |
| @@ -94,8 +159,7 @@ public: | |||
| 94 | 159 | ||
| 95 | private: | 160 | private: |
| 96 | std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> interfacesMap_; | 161 | std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> interfacesMap_; |
| 97 | - std::unordered_map<std::pair<CommAddr, CommProtocol>, std::shared_ptr<NetInstance::ConnInterface>> | 162 | + EndpointToIfaceMap endpointToIfaceMap_; |
| 98 | - endpointToIfaceMap_; | ||
| 99 | NodeType type_; | 163 | NodeType type_; |
| 100 | }; | 164 | }; |
| 101 | 165 | ||
| @@ -126,6 +190,7 @@ public: | |||
| 126 | std::set<u32> GetLevels() const; | 190 | std::set<u32> GetLevels() const; |
| 127 | NetInstancePtr GetNetInstance(u32 level) const; | 191 | NetInstancePtr GetNetInstance(u32 level) const; |
| 128 | std::map<std::string, std::vector<IpAddress>> GetPortAddrMapLayer0() const; | 192 | std::map<std::string, std::vector<IpAddress>> GetPortAddrMapLayer0() const; |
| 193 | + bool TryGetLayer0Address(const std::string& port, IpAddress& addr) const; | ||
| 129 | void SetPortPortAddrMapLayer0(std::map<std::string, std::vector<IpAddress>> portAddrMap); | 194 | void SetPortPortAddrMapLayer0(std::map<std::string, std::vector<IpAddress>> portAddrMap); |
| 130 | std::string Describe() const override; | 195 | std::string Describe() const override; |
| 131 | 196 | ||
| @@ -414,10 +414,10 @@ RankGraph::GetEndpointDesc(uint32_t layer, uint32_t topoInstId, uint32_t* descNu | |||
| 414 | // 一个 iface 可能对应多个 protocol(即多个 EndpointDesc) | 414 | // 一个 iface 可能对应多个 protocol(即多个 EndpointDesc) |
| 415 | const auto& endpointMap = peer->GetEndpointToIfaceMap(); | 415 | const auto& endpointMap = peer->GetEndpointToIfaceMap(); |
| 416 | for (const auto& entry : endpointMap) { | 416 | for (const auto& entry : endpointMap) { |
| 417 | - std::pair<CommAddr, CommProtocol> endpoint = entry.first; | 417 | + const EndpointKey& endpoint = entry.first; |
| 418 | const std::shared_ptr<NetInstance::ConnInterface>& mappedIface = entry.second; | 418 | const std::shared_ptr<NetInstance::ConnInterface>& mappedIface = entry.second; |
| 419 | 419 | ||
| 420 | - if (mappedIface != iface) { | 420 | + if (mappedIface != iface || endpoint.netLayer != layer || endpoint.topoInstId != topoInstId) { |
| 421 | continue; | 421 | continue; |
| 422 | } | 422 | } |
| 423 | 423 | ||
| @@ -430,9 +430,11 @@ RankGraph::GetEndpointDesc(uint32_t layer, uint32_t topoInstId, uint32_t* descNu | |||
| 430 | return HCCL_E_PARA; | 430 | return HCCL_E_PARA; |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | - endpointDesc[count].commAddr = endpoint.first; | 433 | + CHK_RET(static_cast<HcclResult>(EndpointDescInit(&endpointDesc[count], 1))); |
| 434 | - endpointDesc[count].protocol = endpoint.second; | 434 | + endpointDesc[count].commAddr = endpoint.commAddr; |
| 435 | + endpointDesc[count].protocol = endpoint.protocol; | ||
| 435 | endpointDesc[count].loc.locType = AddrPositionToEndpointLoc(iface->GetPos()); | 436 | endpointDesc[count].loc.locType = AddrPositionToEndpointLoc(iface->GetPos()); |
| 437 | + CHK_RET(SetEndpointTopoInfo(endpointDesc[count], layer, topoInstId)); | ||
| 436 | 438 | ||
| 437 | HCCL_INFO( | 439 | HCCL_INFO( |
| 438 | "[RankGraph::GetEndpointDesc] local type is %d, protocol %d", endpointDesc[count].loc.locType, | 440 | "[RankGraph::GetEndpointDesc] local type is %d, protocol %d", endpointDesc[count].loc.locType, |
| @@ -459,14 +461,32 @@ HcclResult RankGraph::GetEndpointInfo( | |||
| 459 | } | 461 | } |
| 460 | 462 | ||
| 461 | // 查找接口 | 463 | // 查找接口 |
| 462 | - auto key = std::make_pair(endpointDesc->commAddr, endpointDesc->protocol); | ||
| 463 | const auto& endpointToIfaceMap = peer->GetEndpointToIfaceMap(); | 464 | const auto& endpointToIfaceMap = peer->GetEndpointToIfaceMap(); |
| 464 | - auto it = endpointToIfaceMap.find(key); | 465 | + u32 endpointNetLayer = UINT32_MAX; |
| 465 | - if (it == endpointToIfaceMap.end()) { | 466 | + u32 endpointTopoInstId = UINT32_MAX; |
| 467 | + const bool hasTopoInfo = GetEndpointTopoInfo(*endpointDesc, endpointNetLayer, endpointTopoInstId); | ||
| 468 | + // 旧描述符未携带拓扑定位信息时仅允许唯一匹配,避免跨层静默选错接口。 | ||
| 469 | + std::shared_ptr<NetInstance::ConnInterface> iface; | ||
| 470 | + for (const auto& entry : endpointToIfaceMap) { | ||
| 471 | + const EndpointKey& key = entry.first; | ||
| 472 | + if (!(key.commAddr == endpointDesc->commAddr) || key.protocol != endpointDesc->protocol) { | ||
| 473 | + continue; | ||
| 474 | + } | ||
| 475 | + if (hasTopoInfo && (key.netLayer != endpointNetLayer || key.topoInstId != endpointTopoInstId)) { | ||
| 476 | + continue; | ||
| 477 | + } | ||
| 478 | + if (iface != nullptr && iface != entry.second) { | ||
| 479 | + HCCL_ERROR( | ||
| 480 | + "[GetEndpointInfo] Ambiguous endpoint, netLayer[%u], topoInstId[%u], protocol[%d]", endpointNetLayer, | ||
| 481 | + endpointTopoInstId, endpointDesc->protocol); | ||
| 482 | + return HCCL_E_PARA; | ||
| 483 | + } | ||
| 484 | + iface = entry.second; | ||
| 485 | + } | ||
| 486 | + if (iface == nullptr) { | ||
| 466 | HCCL_ERROR("[GetEndpointInfo] No matching interface found"); | 487 | HCCL_ERROR("[GetEndpointInfo] No matching interface found"); |
| 467 | return HCCL_E_NOT_FOUND; | 488 | return HCCL_E_NOT_FOUND; |
| 468 | } | 489 | } |
| 469 | - const auto& iface = it->second; | ||
| 470 | // 填充信息 | 490 | // 填充信息 |
| 471 | switch (endpointAttr) { | 491 | switch (endpointAttr) { |
| 472 | case ENDPOINT_ATTR_BW_COEFF: { | 492 | case ENDPOINT_ATTR_BW_COEFF: { |
| @@ -712,9 +732,10 @@ void RankGraph::AddSubPeers(const std::vector<RankId>& rankIds, RankGraph* subRa | |||
| 712 | peers.emplace(subRankId, subPeer); | 732 | peers.emplace(subRankId, subPeer); |
| 713 | const auto& oldEndpointMap = oldPeer->GetEndpointToIfaceMap(); | 733 | const auto& oldEndpointMap = oldPeer->GetEndpointToIfaceMap(); |
| 714 | for (const auto& entry : oldEndpointMap) { | 734 | for (const auto& entry : oldEndpointMap) { |
| 715 | - subPeer->SetEndpointToIface(entry.first.first, entry.first.second, entry.second); | 735 | + subPeer->SetEndpointToIface( |
| 736 | + entry.first.netLayer, entry.first.topoInstId, entry.first.commAddr, entry.first.protocol, entry.second); | ||
| 716 | HCCL_DEBUG( | 737 | HCCL_DEBUG( |
| 717 | - "[SubRankGraph][AddSubPeers] endpointToIfaceMap: protocol[%d] for subRankId[%d]", entry.first.second, | 738 | + "[SubRankGraph][AddSubPeers] endpointToIfaceMap: protocol[%d] for subRankId[%d]", entry.first.protocol, |
| 718 | subRankId); | 739 | subRankId); |
| 719 | } | 740 | } |
| 720 | HCCL_DEBUG( | 741 | HCCL_DEBUG( |
| @@ -44,8 +44,9 @@ GetLinks(NodeId srcId, NodeId dstId, const shared_ptr<Graph<PhyTopo::Node, PhyTo | |||
| 44 | if (phyTopoGraph == nullptr) { | 44 | if (phyTopoGraph == nullptr) { |
| 45 | THROW<NullPtrException>(StringFormat("[GetLinks] phyTopoGraphis nullptr")); | 45 | THROW<NullPtrException>(StringFormat("[GetLinks] phyTopoGraphis nullptr")); |
| 46 | } | 46 | } |
| 47 | + // 统一物理图中仅 P2P 边可作为绕路候选。 | ||
| 47 | phyTopoGraph->TraverseEdge(srcId, dstId, [&](shared_ptr<PhyTopo::Link> link) { | 48 | phyTopoGraph->TraverseEdge(srcId, dstId, [&](shared_ptr<PhyTopo::Link> link) { |
| 48 | - if (link != nullptr) { | 49 | + if (link != nullptr && link->GetType() == LinkType::PEER2PEER) { |
| 49 | links.emplace_back(link); | 50 | links.emplace_back(link); |
| 50 | return; | 51 | return; |
| 51 | } | 52 | } |
| @@ -67,6 +68,10 @@ void AddDetourLink( | |||
| 67 | if (innerNetInst == nullptr) { | 68 | if (innerNetInst == nullptr) { |
| 68 | THROW<NullPtrException>(StringFormat("[AddDetourLink] innerGroup is nullptr")); | 69 | THROW<NullPtrException>(StringFormat("[AddDetourLink] innerGroup is nullptr")); |
| 69 | } | 70 | } |
| 71 | + if (data.srcNetInstPeer == nullptr || data.dstNetInstPeer == nullptr) { | ||
| 72 | + THROW<NullPtrException>( | ||
| 73 | + StringFormat("[DetourService][InsertDetourLinks][AddDetourLink] virtual peer is nullptr")); | ||
| 74 | + } | ||
| 70 | u32 hop = 2; // 目前绕路hop一定是2 | 75 | u32 hop = 2; // 目前绕路hop一定是2 |
| 71 | for (const auto& src2detLink : src2detVec) { | 76 | for (const auto& src2detLink : src2detVec) { |
| 72 | for (const auto& det2dstLink : det2dstVec) { | 77 | for (const auto& det2dstLink : det2dstVec) { |
| @@ -97,14 +102,21 @@ void AddDetourLink( | |||
| 97 | std::set<string> src2detPorts = src2detLink->GetSourceIFace()->GetPorts(); | 102 | std::set<string> src2detPorts = src2detLink->GetSourceIFace()->GetPorts(); |
| 98 | std::set<string> det2dstPorts = det2dstLink->GetTargetIFace()->GetPorts(); | 103 | std::set<string> det2dstPorts = det2dstLink->GetTargetIFace()->GetPorts(); |
| 99 | if (src2detPorts.size() != 1 || det2dstPorts.size() != 1) { | 104 | if (src2detPorts.size() != 1 || det2dstPorts.size() != 1) { |
| 100 | - THROW<InvalidParamsException>( | 105 | + HCCL_WARNING( |
| 101 | - "[DetourService][InsertDetourLinks][AddDetourLink] Peer to Peer port num error"); | 106 | + "[DetourService][InsertDetourLinks][AddDetourLink] Ignore unmatched P2P candidate, " |
| 107 | + "srcPortNum[%zu] dstPortNum[%zu]", | ||
| 108 | + src2detPorts.size(), det2dstPorts.size()); | ||
| 109 | + continue; | ||
| 102 | } | 110 | } |
| 103 | 111 | ||
| 104 | - // 取出对应的端口,然后去ranktableInfo中查对应端口的地址信息 | 112 | + // 绕路两端口均须属于 RankTable layer 0。 |
| 105 | - // todo 逻辑判断一下只取第一个端口是否正确? | 113 | + IpAddress src2detAddr; |
| 106 | - IpAddress src2detAddr = data.srcNetInstPeer->GetPortAddrMapLayer0()[*src2detPorts.begin()][0]; | 114 | + IpAddress det2dstAddr; |
| 107 | - IpAddress det2dstAddr = data.dstNetInstPeer->GetPortAddrMapLayer0()[*det2dstPorts.begin()][0]; | 115 | + if (!data.srcNetInstPeer->TryGetLayer0Address(*src2detPorts.begin(), src2detAddr) |
| 116 | + || !data.dstNetInstPeer->TryGetLayer0Address(*det2dstPorts.begin(), det2dstAddr)) { | ||
| 117 | + HCCL_WARNING("[DetourService][InsertDetourLinks][AddDetourLink] Ignore P2P candidate not in layer0"); | ||
| 118 | + continue; | ||
| 119 | + } | ||
| 108 | 120 | ||
| 109 | // 构造InterFace对象用于后续生成Link | 121 | // 构造InterFace对象用于后续生成Link |
| 110 | shared_ptr<NetInstance::ConnInterface> sourceIface = make_shared<NetInstance::ConnInterface>( | 122 | shared_ptr<NetInstance::ConnInterface> sourceIface = make_shared<NetInstance::ConnInterface>( |
| @@ -125,10 +137,6 @@ void AddDetourLink( | |||
| 125 | innerNetInst->AddLink(recvEdge); | 137 | innerNetInst->AddLink(recvEdge); |
| 126 | 138 | ||
| 127 | data.srcNetInstPeer->AddConnInterface(0, sourceIface); | 139 | data.srcNetInstPeer->AddConnInterface(0, sourceIface); |
| 128 | - if (data.dstNetInstPeer == nullptr) { | ||
| 129 | - THROW<NullPtrException>( | ||
| 130 | - StringFormat("[DetourService][InsertDetourLinks][AddDetourLink] dstVirtPeer is nullptr")); | ||
| 131 | - } | ||
| 132 | data.dstNetInstPeer->AddConnInterface(0, targetIface); | 140 | data.dstNetInstPeer->AddConnInterface(0, targetIface); |
| 133 | 141 | ||
| 134 | HCCL_DEBUG( | 142 | HCCL_DEBUG( |
| @@ -304,7 +312,7 @@ void AddDetourLinks( | |||
| 304 | std::unordered_map<LocalId, unordered_map<LocalId, vector<LocalId>>>& detourTable, | 312 | std::unordered_map<LocalId, unordered_map<LocalId, vector<LocalId>>>& detourTable, |
| 305 | std::unordered_map<LocalId, u32>& tableIds, const RankTableInfo* rankTable) | 313 | std::unordered_map<LocalId, u32>& tableIds, const RankTableInfo* rankTable) |
| 306 | { | 314 | { |
| 307 | - auto phyTopoGraph = phyTopo->GetTopoGraph(0); | 315 | + auto phyTopoGraph = phyTopo->GetTopoGraph(); |
| 308 | NetInstance* innerNetInst = rankGraph->GetNetInstanceByRankId(0, rankGraph->GetMyRank()); | 316 | NetInstance* innerNetInst = rankGraph->GetNetInstanceByRankId(0, rankGraph->GetMyRank()); |
| 309 | if (innerNetInst == nullptr) { | 317 | if (innerNetInst == nullptr) { |
| 310 | THROW<NullPtrException>(StringFormat("[DetourService] innerNetInst is nullptr")); | 318 | THROW<NullPtrException>(StringFormat("[DetourService] innerNetInst is nullptr")); |
| @@ -10,10 +10,18 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | + | ||
| 14 | + | ||
| 13 | 15 | ||
| 14 | 16 | ||
| 17 | + | ||
| 15 | 18 | ||
| 16 | 19 | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +namespace hcomm { | ||
| 23 | +HcclResult HccpRaGetDevBaseAttr(void* ctxHandle, struct DevBaseAttr* attr); | ||
| 24 | +} | ||
| 17 | 25 | ||
| 18 | namespace Hccl { | 26 | namespace Hccl { |
| 19 | 27 | ||
| @@ -65,18 +73,29 @@ const RankLevelInfo& RankGraphBuilder::GetRankLevelInfoByNetLayer(const NewRankI | |||
| 65 | return *it; | 73 | return *it; |
| 66 | } | 74 | } |
| 67 | 75 | ||
| 68 | -std::vector<shared_ptr<PhyTopo::Link>> GetPeer2NetPhyLinks(u32 netLayer, LocalId localId) | 76 | +u32 RankGraphBuilder::GetLocalDeviceId() const |
| 69 | { | 77 | { |
| 70 | - const shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyGraph = PhyTopo::GetInstance()->GetTopoGraph(netLayer); | 78 | + if (rankGraph_ == nullptr) { |
| 79 | + THROW<NullPtrException>(StringFormat("[RankGraphBuilder][GetLocalDeviceId] rankGraph is nullptr")); | ||
| 80 | + } | ||
| 81 | + auto peer = rankGraph_->GetPeer(myRank_); | ||
| 82 | + if (peer == nullptr) { | ||
| 83 | + THROW<NullPtrException>(StringFormat("[RankGraphBuilder][GetLocalDeviceId] local peer is nullptr")); | ||
| 84 | + } | ||
| 85 | + return peer->GetDeviceId(); | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +std::vector<shared_ptr<PhyTopo::Link>> GetPeer2NetPhyLinks(LocalId localId) | ||
| 89 | +{ | ||
| 90 | + const shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyGraph = PhyTopo::GetInstance()->GetTopoGraph(); | ||
| 71 | if (phyGraph == nullptr) { | 91 | if (phyGraph == nullptr) { |
| 72 | - THROW<InvalidParamsException>(StringFormat( | 92 | + THROW<InvalidParamsException>( |
| 73 | - "[RankGraphBuilder][GetPhyLink] localId[%d] is not level[%u] in" | 93 | + StringFormat("[RankGraphBuilder][GetPhyLink] physical topo graph is null for localId[%d].", localId)); |
| 74 | - " topo.json, not match rankTable.", | ||
| 75 | - localId, netLayer)); | ||
| 76 | } | 94 | } |
| 77 | std::vector<shared_ptr<PhyTopo::Link>> links; | 95 | std::vector<shared_ptr<PhyTopo::Link>> links; |
| 96 | + // 统一物理图包含多种边,此处仅收集 PEER2NET 边。 | ||
| 78 | phyGraph->TraverseEdge(PhyTopo::Peer::GetId(localId), [&](shared_ptr<PhyTopo::Link> link) { | 97 | phyGraph->TraverseEdge(PhyTopo::Peer::GetId(localId), [&](shared_ptr<PhyTopo::Link> link) { |
| 79 | - if (link != nullptr) { | 98 | + if (link != nullptr && link->GetType() == LinkType::PEER2NET) { |
| 80 | links.push_back(link); | 99 | links.push_back(link); |
| 81 | } | 100 | } |
| 82 | }); | 101 | }); |
| @@ -88,12 +107,223 @@ std::vector<shared_ptr<PhyTopo::Link>> GetPeer2NetPhyLinks(u32 netLayer, LocalId | |||
| 88 | return links; | 107 | return links; |
| 89 | } | 108 | } |
| 90 | 109 | ||
| 110 | +bool IsPeer2NetLinkMatched(const shared_ptr<PhyTopo::Link>& link, const AddressInfo& addrInfo) | ||
| 111 | +{ | ||
| 112 | + if (link == nullptr || link->GetType() != LinkType::PEER2NET || link->GetSourceIFace() == nullptr) { | ||
| 113 | + return false; | ||
| 114 | + } | ||
| 115 | + // 端口有交集时,该物理边才属于当前 RankTable 地址。 | ||
| 116 | + const auto& phyPorts = link->GetSourceIFace()->GetPorts(); | ||
| 117 | + return std::any_of(addrInfo.ports.begin(), addrInfo.ports.end(), [&phyPorts](const std::string& port) { | ||
| 118 | + return phyPorts.count(port) != 0; | ||
| 119 | + }); | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +std::vector<shared_ptr<PhyTopo::Link>> GetMatchedPeer2NetPhyLinks( | ||
| 123 | + const vector<shared_ptr<PhyTopo::Link>>& links, const AddressInfo& addrInfo, | ||
| 124 | + const std::map<PlaneId, LinkProtocol>& planeUbProtocols) | ||
| 125 | +{ | ||
| 126 | + vector<shared_ptr<PhyTopo::Link>> matchedLinks; | ||
| 127 | + matchedLinks.reserve(links.size()); | ||
| 128 | + const auto protocolIter = planeUbProtocols.find(addrInfo.planeId); | ||
| 129 | + const bool hasPlaneUbProtocol = protocolIter != planeUbProtocols.end(); | ||
| 130 | + const LinkProtocol planeUbProtocol | ||
| 131 | + = hasPlaneUbProtocol ? protocolIter->second : LinkProtocol(LinkProtocol::INVALID); | ||
| 132 | + std::copy_if( | ||
| 133 | + links.begin(), links.end(), std::back_inserter(matchedLinks), | ||
| 134 | + [&addrInfo, hasPlaneUbProtocol, planeUbProtocol](const shared_ptr<PhyTopo::Link>& link) { | ||
| 135 | + if (!IsPeer2NetLinkMatched(link, addrInfo)) { | ||
| 136 | + return false; | ||
| 137 | + } | ||
| 138 | + return !hasPlaneUbProtocol || link->GetLinkProtocols().count(planeUbProtocol) != 0; | ||
| 139 | + }); | ||
| 140 | + return matchedLinks; | ||
| 141 | +} | ||
| 142 | + | ||
| 143 | +namespace { | ||
| 144 | + | ||
| 145 | + bool | ||
| 146 | + IsSamePhyInterface(const shared_ptr<PhyTopo::ConnInterface>& lhs, const shared_ptr<PhyTopo::ConnInterface>& rhs) | ||
| 147 | + { | ||
| 148 | + if (lhs == nullptr || rhs == nullptr) { | ||
| 149 | + return lhs == rhs; | ||
| 150 | + } | ||
| 151 | + return *lhs == *rhs; | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + bool IsSamePeer2NetLinkExceptTopoInstId(const shared_ptr<PhyTopo::Link>& lhs, const shared_ptr<PhyTopo::Link>& rhs) | ||
| 155 | + { | ||
| 156 | + if (lhs == nullptr || rhs == nullptr) { | ||
| 157 | + return lhs == rhs; | ||
| 158 | + } | ||
| 159 | + return lhs->GetSourceNode() == rhs->GetSourceNode() && lhs->GetTargetNode() == rhs->GetTargetNode() | ||
| 160 | + && lhs->GetType() == rhs->GetType() && lhs->GetLinkProtocols() == rhs->GetLinkProtocols() | ||
| 161 | + && lhs->GetLinkDirection() == rhs->GetLinkDirection() && lhs->GetTopoType() == rhs->GetTopoType() | ||
| 162 | + && lhs->GetHop() == rhs->GetHop() && IsSamePhyInterface(lhs->GetSourceIFace(), rhs->GetSourceIFace()) | ||
| 163 | + && IsSamePhyInterface(lhs->GetTargetIFace(), rhs->GetTargetIFace()); | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + std::vector<shared_ptr<PhyTopo::Link>> | ||
| 167 | + DeduplicatePeer2NetPhyLinks(std::vector<shared_ptr<PhyTopo::Link>> matchedLinks) | ||
| 168 | + { | ||
| 169 | + std::vector<shared_ptr<PhyTopo::Link>> uniqueLinks; | ||
| 170 | + uniqueLinks.reserve(matchedLinks.size()); | ||
| 171 | + for (const auto& link : matchedLinks) { | ||
| 172 | + const auto duplicate | ||
| 173 | + = std::find_if(uniqueLinks.begin(), uniqueLinks.end(), [&link](const auto& uniqueLink) { | ||
| 174 | + return IsSamePeer2NetLinkExceptTopoInstId(link, uniqueLink); | ||
| 175 | + }); | ||
| 176 | + if (duplicate == uniqueLinks.end()) { | ||
| 177 | + uniqueLinks.emplace_back(link); | ||
| 178 | + continue; | ||
| 179 | + } | ||
| 180 | + const u32 oldTopoInstId = (*duplicate)->GetTopoInstId(); | ||
| 181 | + const u32 newTopoInstId = link->GetTopoInstId(); | ||
| 182 | + if (newTopoInstId < oldTopoInstId) { | ||
| 183 | + *duplicate = link; | ||
| 184 | + } | ||
| 185 | + // 等价物理边共用一条逻辑边,并保留较小的拓扑实例 ID。 | ||
| 186 | + HCCL_DEBUG( | ||
| 187 | + "[RankGraphBuilder][DeduplicatePeer2NetPhyLinks] ignore topoInstId[%u], keep topoInstId[%u].", | ||
| 188 | + std::max(oldTopoInstId, newTopoInstId), std::min(oldTopoInstId, newTopoInstId)); | ||
| 189 | + } | ||
| 190 | + return uniqueLinks; | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + std::vector<shared_ptr<PhyTopo::Link>> GetMatchedPeer2NetPhyLinksForLayer( | ||
| 194 | + u32 netLayer, const vector<shared_ptr<PhyTopo::Link>>& links, const AddressInfo& addrInfo, | ||
| 195 | + const std::map<PlaneId, LinkProtocol>& planeUbProtocols) | ||
| 196 | + { | ||
| 197 | + std::vector<shared_ptr<PhyTopo::Link>> matchedLinks | ||
| 198 | + = GetMatchedPeer2NetPhyLinks(links, addrInfo, planeUbProtocols); | ||
| 199 | + if (netLayer == 0) { | ||
| 200 | + // layer 0 保持 topo 描述语义,只对 RankTable 定义的高层网络去重。 | ||
| 201 | + return matchedLinks; | ||
| 202 | + } | ||
| 203 | + return DeduplicatePeer2NetPhyLinks(std::move(matchedLinks)); | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + shared_ptr<NetInstance::Fabric> GetOrCreateFabricNode( | ||
| 207 | + FabricId fabId, const PlaneId& planeId, vector<shared_ptr<NetInstance::Fabric>>& fabNodes, | ||
| 208 | + const shared_ptr<NetInstance>& netInst) | ||
| 209 | + { | ||
| 210 | + if (fabNodes[fabId] == nullptr) { | ||
| 211 | + fabNodes[fabId] = make_shared<NetInstance::Fabric>(fabId, planeId); | ||
| 212 | + netInst->AddNode(fabNodes[fabId]); | ||
| 213 | + } | ||
| 214 | + return fabNodes[fabId]; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | +} // namespace | ||
| 218 | + | ||
| 219 | +const vector<shared_ptr<PhyTopo::Link>>& RankGraphBuilder::GetPeer2NetPhyLinksCached(LocalId localId) | ||
| 220 | +{ | ||
| 221 | + auto iter = peer2NetPhyLinksCache_.find(localId); | ||
| 222 | + if (iter == peer2NetPhyLinksCache_.end()) { | ||
| 223 | + iter = peer2NetPhyLinksCache_.emplace(localId, GetPeer2NetPhyLinks(localId)).first; | ||
| 224 | + } | ||
| 225 | + return iter->second; | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +LinkProtocol RankGraphBuilder::ResolveUbProtocolByEid(const AddressInfo& addrInfo, bool& supportsRtp) const | ||
| 229 | +{ | ||
| 230 | + if (addrInfo.addrType != AddrType::EID) { | ||
| 231 | + THROW<InvalidParamsException>(StringFormat( | ||
| 232 | + "[RankGraphBuilder][ResolveUbProtocolByEid] addr[%s] is not an EID, cannot distinguish UB protocol.", | ||
| 233 | + addrInfo.addr.Describe().c_str())); | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + const auto rdmaHandle = RdmaHandleManager::GetInstance().GetByIp(GetLocalDeviceId(), addrInfo.addr); | ||
| 237 | + if (rdmaHandle == nullptr) { | ||
| 238 | + THROW<NullPtrException>(StringFormat( | ||
| 239 | + "[RankGraphBuilder][ResolveUbProtocolByEid] get context failed for EID[%s].", | ||
| 240 | + addrInfo.addr.Describe().c_str())); | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + DevBaseAttr devBaseAttr{}; | ||
| 244 | + const HcclResult ret = hcomm::HccpRaGetDevBaseAttr(rdmaHandle, &devBaseAttr); | ||
| 245 | + if (ret != HCCL_SUCCESS) { | ||
| 246 | + THROW<InternalException>(StringFormat( | ||
| 247 | + "[RankGraphBuilder][ResolveUbProtocolByEid] get device base attr failed for EID[%s], ret[%d].", | ||
| 248 | + addrInfo.addr.Describe().c_str(), static_cast<int>(ret))); | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + bool hasCtp = false; | ||
| 252 | + bool hasRtp = false; | ||
| 253 | + for (u32 priority = 0U; priority < static_cast<u32>(MAX_PRIORITY_CNT); ++priority) { | ||
| 254 | + const CtxSlInfo& priorityInfo = devBaseAttr.ub.priorityInfo[priority]; | ||
| 255 | + hasCtp = hasCtp || priorityInfo.tpType.bs.ctp != 0; | ||
| 256 | + hasRtp = hasRtp || priorityInfo.tpType.bs.rtp != 0; | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + // topo 中 UB_CTP 边同时承载 UB_MEM;EID 支持 CTP 时优先保留该边, | ||
| 260 | + // 仅当 EID 不支持 CTP 但支持 RTP 时匹配 UB_TP 边。 | ||
| 261 | + supportsRtp = hasRtp; | ||
| 262 | + if (hasCtp) { | ||
| 263 | + HCCL_INFO( | ||
| 264 | + "[RankGraphBuilder][ResolveUbProtocolByEid] EID[%s] protocol[UB_CTP], hasCtp[%d], hasRtp[%d].", | ||
| 265 | + addrInfo.addr.Describe().c_str(), static_cast<int>(hasCtp), static_cast<int>(hasRtp)); | ||
| 266 | + return LinkProtocol::UB_CTP; | ||
| 267 | + } | ||
| 268 | + if (hasRtp) { | ||
| 269 | + HCCL_INFO( | ||
| 270 | + "[RankGraphBuilder][ResolveUbProtocolByEid] EID[%s] protocol[UB_TP], hasCtp[%d], hasRtp[%d].", | ||
| 271 | + addrInfo.addr.Describe().c_str(), static_cast<int>(hasCtp), static_cast<int>(hasRtp)); | ||
| 272 | + return LinkProtocol::UB_TP; | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + THROW<InvalidParamsException>(StringFormat( | ||
| 276 | + "[RankGraphBuilder][ResolveUbProtocolByEid] EID[%s] has neither CTP nor RTP in priorityInfo.", | ||
| 277 | + addrInfo.addr.Describe().c_str())); | ||
| 278 | +} | ||
| 279 | + | ||
| 280 | +std::map<PlaneId, LinkProtocol> RankGraphBuilder::ResolvePlaneUbProtocols(u32 netLayer, std::set<PlaneId>& ctpRtpPlanes) | ||
| 281 | +{ | ||
| 282 | + const auto& levelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[myRank_], netLayer); | ||
| 283 | + | ||
| 284 | + ctpRtpPlanes.clear(); | ||
| 285 | + std::map<PlaneId, LinkProtocol> planeProtocols; | ||
| 286 | + std::map<PlaneId, bool> planeExposeUbTp; | ||
| 287 | + for (const AddressInfo& addrInfo : levelInfo.rankAddrs) { | ||
| 288 | + if (addrInfo.addr == IpAddress() || addrInfo.addrType != AddrType::EID) { | ||
| 289 | + continue; | ||
| 290 | + } | ||
| 291 | + bool supportsRtp = false; | ||
| 292 | + const LinkProtocol currentProtocol = ResolveUbProtocolByEid(addrInfo, supportsRtp); | ||
| 293 | + const bool exposeUbTp = currentProtocol == LinkProtocol::UB_CTP && supportsRtp; | ||
| 294 | + HCCL_INFO( | ||
| 295 | + "[RankGraphBuilder][ResolvePlaneUbProtocols] netLayer[%u] planeId[%s] EID[%s] protocol[%s].", netLayer, | ||
| 296 | + addrInfo.planeId.c_str(), addrInfo.addr.Describe().c_str(), currentProtocol.Describe().c_str()); | ||
| 297 | + const auto result = planeProtocols.emplace(addrInfo.planeId, currentProtocol); | ||
| 298 | + if (!result.second && result.first->second != currentProtocol) { | ||
| 299 | + THROW<InvalidParamsException>(StringFormat( | ||
| 300 | + "[RankGraphBuilder][ResolvePlaneUbProtocols] netLayer[%u] planeId[%s] contains mixed UB " | ||
| 301 | + "protocols[%s, %s].", | ||
| 302 | + netLayer, addrInfo.planeId.c_str(), result.first->second.Describe().c_str(), | ||
| 303 | + currentProtocol.Describe().c_str())); | ||
| 304 | + } | ||
| 305 | + const auto capabilityResult = planeExposeUbTp.emplace(addrInfo.planeId, exposeUbTp); | ||
| 306 | + if (!capabilityResult.second && capabilityResult.first->second != exposeUbTp) { | ||
| 307 | + THROW<InvalidParamsException>(StringFormat( | ||
| 308 | + "[RankGraphBuilder][ResolvePlaneUbProtocols] netLayer[%u] planeId[%s] contains mixed UB " | ||
| 309 | + "capabilities, exposeUbTp[%d, %d].", | ||
| 310 | + netLayer, addrInfo.planeId.c_str(), static_cast<int>(capabilityResult.first->second), | ||
| 311 | + static_cast<int>(exposeUbTp))); | ||
| 312 | + } | ||
| 313 | + if (exposeUbTp) { | ||
| 314 | + ctpRtpPlanes.insert(addrInfo.planeId); | ||
| 315 | + } | ||
| 316 | + } | ||
| 317 | + return planeProtocols; | ||
| 318 | +} | ||
| 319 | + | ||
| 91 | void RankGraphBuilder::AddPeer2NetLink( | 320 | void RankGraphBuilder::AddPeer2NetLink( |
| 92 | const u32 netLayer, const string& netInstId, RankId rankId, const AddressInfo& addrInfo, | 321 | const u32 netLayer, const string& netInstId, RankId rankId, const AddressInfo& addrInfo, |
| 93 | - const shared_ptr<NetInstance::Fabric>& fabNode, const vector<shared_ptr<PhyTopo::Link>>& links) | 322 | + const shared_ptr<NetInstance::Fabric>& fabNode, const vector<shared_ptr<PhyTopo::Link>>& matchedLinks, |
| 323 | + bool exposeUbTp) | ||
| 94 | { | 324 | { |
| 95 | - for (shared_ptr<PhyTopo::Link> link : links) { | 325 | + for (shared_ptr<PhyTopo::Link> link : matchedLinks) { |
| 96 | - if (link->GetSourceIFace() == nullptr) { | 326 | + if (link == nullptr || link->GetSourceIFace() == nullptr) { |
| 97 | continue; | 327 | continue; |
| 98 | } | 328 | } |
| 99 | std::set<std::string> ports = link->GetSourceIFace()->GetPorts(); | 329 | std::set<std::string> ports = link->GetSourceIFace()->GetPorts(); |
| @@ -109,22 +339,25 @@ void RankGraphBuilder::AddPeer2NetLink( | |||
| 109 | // 获取topoInstId topoType | 339 | // 获取topoInstId topoType |
| 110 | u32 topoInstId = link->GetTopoInstId(); | 340 | u32 topoInstId = link->GetTopoInstId(); |
| 111 | auto topoType = link->GetTopoType(); | 341 | auto topoType = link->GetTopoType(); |
| 342 | + std::set<LinkProtocol> linkProtocols = link->GetLinkProtocols(); | ||
| 343 | + if (exposeUbTp && linkProtocols.count(LinkProtocol::UB_CTP) != 0) { | ||
| 344 | + // CTP/RTP 共存时仍复用 CTP 物理边,仅扩展逻辑协议能力。 | ||
| 345 | + linkProtocols.insert(LinkProtocol::UB_TP); | ||
| 346 | + } | ||
| 112 | 347 | ||
| 113 | // 构造 RankGraph 的 PeerIface | 348 | // 构造 RankGraph 的 PeerIface |
| 114 | shared_ptr<NetInstance::ConnInterface> peerIface = make_shared<NetInstance::ConnInterface>( | 349 | shared_ptr<NetInstance::ConnInterface> peerIface = make_shared<NetInstance::ConnInterface>( |
| 115 | - addrInfo.addr, rankGraphPorts, link->GetSourceIFace()->GetPos(), LinkType::PEER2NET, | 350 | + addrInfo.addr, rankGraphPorts, link->GetSourceIFace()->GetPos(), LinkType::PEER2NET, linkProtocols, |
| 116 | - link->GetLinkProtocols(), topoType, topoInstId); | 351 | + topoType, topoInstId); |
| 117 | // 获取 rankId 对应 PeerNode | 352 | // 获取 rankId 对应 PeerNode |
| 118 | shared_ptr<NetInstance::Peer> peerNode = peers_.at(rankId); | 353 | shared_ptr<NetInstance::Peer> peerNode = peers_.at(rankId); |
| 119 | peerNode->AddConnInterface(netLayer, peerIface); | 354 | peerNode->AddConnInterface(netLayer, peerIface); |
| 120 | 355 | ||
| 121 | // 构造 peer2netLink 和 net2peerLink 两条link | 356 | // 构造 peer2netLink 和 net2peerLink 两条link |
| 122 | shared_ptr<NetInstance::Link> peer2netLink = make_shared<NetInstance::Link>( | 357 | shared_ptr<NetInstance::Link> peer2netLink = make_shared<NetInstance::Link>( |
| 123 | - peerNode, fabNode, peerIface, nullptr, LinkType::PEER2NET, link->GetLinkProtocols(), LinkDirection::BOTH, | 358 | + peerNode, fabNode, peerIface, nullptr, LinkType::PEER2NET, linkProtocols, LinkDirection::BOTH, 2); |
| 124 | - 2); | ||
| 125 | shared_ptr<NetInstance::Link> net2peerLink = make_shared<NetInstance::Link>( | 359 | shared_ptr<NetInstance::Link> net2peerLink = make_shared<NetInstance::Link>( |
| 126 | - fabNode, peerNode, nullptr, peerIface, LinkType::PEER2NET, link->GetLinkProtocols(), LinkDirection::BOTH, | 360 | + fabNode, peerNode, nullptr, peerIface, LinkType::PEER2NET, linkProtocols, LinkDirection::BOTH, 2); |
| 127 | - 2); | ||
| 128 | 361 | ||
| 129 | // 插入 link | 362 | // 插入 link |
| 130 | tempNetInsts_[netLayer][netInstId]->AddLink(peer2netLink); | 363 | tempNetInsts_[netLayer][netInstId]->AddLink(peer2netLink); |
| @@ -156,7 +389,6 @@ void RankGraphBuilder::AddFabricInfo(u32 netLayer) | |||
| 156 | THROW<NotSupportException>( | 389 | THROW<NotSupportException>( |
| 157 | StringFormat("[RankGraphBuilder][AddFabricInfo] NetInstance is not CLOS, not support add fabric.")); | 390 | StringFormat("[RankGraphBuilder][AddFabricInfo] NetInstance is not CLOS, not support add fabric.")); |
| 158 | } | 391 | } |
| 159 | - set<RankId> inRanks = netInst->GetRankIds(); | ||
| 160 | string netInstId = netInst->GetNetInstId(); | 392 | string netInstId = netInst->GetNetInstId(); |
| 161 | const auto& myLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[myRank_], netLayer); | 393 | const auto& myLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[myRank_], netLayer); |
| 162 | // 根据planeId确认Fabric个数,每个fabricId对应一个planeId | 394 | // 根据planeId确认Fabric个数,每个fabricId对应一个planeId |
| @@ -167,37 +399,37 @@ void RankGraphBuilder::AddFabricInfo(u32 netLayer) | |||
| 167 | "[RankGraphBuilder][AddFabricInfo] current rankId[%d] netLayer[%u] group no net plane", myRank_, netLayer); | 399 | "[RankGraphBuilder][AddFabricInfo] current rankId[%d] netLayer[%u] group no net plane", myRank_, netLayer); |
| 168 | return; | 400 | return; |
| 169 | } | 401 | } |
| 402 | + // topo 不再携带 net_layer;以本地 EID 的协议查询结果筛选对应物理边。 | ||
| 403 | + std::set<PlaneId> ctpRtpPlanes; | ||
| 404 | + const std::map<PlaneId, LinkProtocol> planeUbProtocols = ResolvePlaneUbProtocols(netLayer, ctpRtpPlanes); | ||
| 170 | vector<shared_ptr<NetInstance::Fabric>> fabNodes(planeId2Node.size(), nullptr); | 405 | vector<shared_ptr<NetInstance::Fabric>> fabNodes(planeId2Node.size(), nullptr); |
| 406 | + const shared_ptr<NetInstance>& buildingNetInst = tempNetInsts_[netLayer][netInstId]; | ||
| 171 | 407 | ||
| 172 | // 遍历每一个rankId,每个rankId都增加 peer2net 和 net2peer 两条链路 | 408 | // 遍历每一个rankId,每个rankId都增加 peer2net 和 net2peer 两条链路 |
| 173 | - for (RankId srcRankId : inRanks) { | 409 | + for (RankId srcRankId : netInst->GetRankIds()) { |
| 174 | const auto& srcLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[srcRankId], netLayer); | 410 | const auto& srcLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[srcRankId], netLayer); |
| 175 | - const vector<AddressInfo>& addrs = srcLevelInfo.rankAddrs; | ||
| 176 | // rankId对应的物理逻辑localId | 411 | // rankId对应的物理逻辑localId |
| 177 | LocalId localId = rankGraph_->GetLocalId(srcRankId); | 412 | LocalId localId = rankGraph_->GetLocalId(srcRankId); |
| 178 | - // 从物理拓扑图中找出 localId在 netLayer 中所有的peer2Net的边。 | 413 | + // 从物理拓扑图中找出 localId 的所有 peer2Net 边。 |
| 179 | - std::vector<shared_ptr<PhyTopo::Link>> links = GetPeer2NetPhyLinks(netLayer, localId); | 414 | + const auto& links = GetPeer2NetPhyLinksCached(localId); |
| 180 | // 遍历ranktable中的addr,有几个addr就有几条peer2net的边 | 415 | // 遍历ranktable中的addr,有几个addr就有几条peer2net的边 |
| 181 | - for (AddressInfo addrInfo : addrs) { | 416 | + for (const AddressInfo& addrInfo : srcLevelInfo.rankAddrs) { |
| 182 | - if (addrInfo.addr == IpAddress()) { | 417 | + if (addrInfo.addr == IpAddress() || planeId2Node.count(addrInfo.planeId) == 0) { |
| 183 | continue; | 418 | continue; |
| 184 | } | 419 | } |
| 185 | - | 420 | + const vector<shared_ptr<PhyTopo::Link>> matchedLinks |
| 186 | - if (planeId2Node.count(addrInfo.planeId) == 0) { | 421 | + = GetMatchedPeer2NetPhyLinksForLayer(netLayer, links, addrInfo, planeUbProtocols); |
| 422 | + if (matchedLinks.empty()) { | ||
| 187 | continue; | 423 | continue; |
| 188 | } | 424 | } |
| 189 | FabricId fabId = planeId2Node[addrInfo.planeId]; | 425 | FabricId fabId = planeId2Node[addrInfo.planeId]; |
| 190 | // 若 fabNodes[fabId] 不存在则创建 如果存在则获取fabNode | 426 | // 若 fabNodes[fabId] 不存在则创建 如果存在则获取fabNode |
| 191 | - shared_ptr<NetInstance::Fabric> fabNode; | 427 | + shared_ptr<NetInstance::Fabric> fabNode |
| 192 | - if (fabNodes[fabId] == nullptr) { | 428 | + = GetOrCreateFabricNode(fabId, addrInfo.planeId, fabNodes, buildingNetInst); |
| 193 | - fabNode = make_shared<NetInstance::Fabric>(fabId, addrInfo.planeId); | ||
| 194 | - tempNetInsts_[netLayer][netInstId]->AddNode(fabNode); | ||
| 195 | - fabNodes[fabId] = fabNode; | ||
| 196 | - } else { | ||
| 197 | - fabNode = fabNodes[fabId]; | ||
| 198 | - } | ||
| 199 | // 插入peer和fabric的peer2net和net2peer两条link | 429 | // 插入peer和fabric的peer2net和net2peer两条link |
| 200 | - AddPeer2NetLink(netLayer, netInstId, srcRankId, addrInfo, fabNode, links); | 430 | + AddPeer2NetLink( |
| 431 | + netLayer, netInstId, srcRankId, addrInfo, fabNode, matchedLinks, | ||
| 432 | + ctpRtpPlanes.count(addrInfo.planeId) != 0); | ||
| 201 | } | 433 | } |
| 202 | } | 434 | } |
| 203 | 435 | ||
| @@ -209,7 +441,7 @@ void RankGraphBuilder::AddFabricInfo(u32 netLayer) | |||
| 209 | void RankGraphBuilder::AddTopoDescFabricInfo() | 441 | void RankGraphBuilder::AddTopoDescFabricInfo() |
| 210 | { | 442 | { |
| 211 | // 1. 获取物理拓扑图 | 443 | // 1. 获取物理拓扑图 |
| 212 | - auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0); | 444 | + auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(); |
| 213 | if (phyTopoGraph == nullptr) { | 445 | if (phyTopoGraph == nullptr) { |
| 214 | THROW<NullPtrException>(StringFormat("[RankGraphBuilder][AddTopoDescFabricInfo] phyTopoGraph is nullptr")); | 446 | THROW<NullPtrException>(StringFormat("[RankGraphBuilder][AddTopoDescFabricInfo] phyTopoGraph is nullptr")); |
| 215 | } | 447 | } |
| @@ -224,15 +456,19 @@ void RankGraphBuilder::AddTopoDescFabricInfo() | |||
| 224 | std::string netInstId = innerNetInstance->GetNetInstId(); | 456 | std::string netInstId = innerNetInstance->GetNetInstId(); |
| 225 | std::set<RankId> rankIds = innerNetInstance->GetRankIds(); | 457 | std::set<RankId> rankIds = innerNetInstance->GetRankIds(); |
| 226 | 458 | ||
| 227 | - // 存储所有fabric节点,key为topoInstId | 459 | + // Fabric 的归属以 RankTable planeId 为准,topoInstId 仅保留为拓扑实例属性。 |
| 228 | - std::map<u32, std::shared_ptr<NetInstance::Fabric>> fabNodes; | 460 | + const auto& myLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[myRank_], 0); |
| 461 | + const std::map<PlaneId, FabricId> planeId2Node = GetFabricsFromAddrInfo(myLevelInfo.rankAddrs); | ||
| 462 | + if (planeId2Node.empty()) { | ||
| 463 | + HCCL_WARNING("[RankGraphBuilder][AddTopoDescFabricInfo] rankId[%u] layer0 has no plane", myRank_); | ||
| 464 | + return; | ||
| 465 | + } | ||
| 466 | + vector<shared_ptr<NetInstance::Fabric>> fabNodes(planeId2Node.size(), nullptr); | ||
| 229 | 467 | ||
| 230 | - auto peer = rankGraph_->GetPeer(rankGraph_->GetMyRank()); | 468 | + // 3. 遍历所有 rank 节点,根据端口匹配到的 planeId 创建 Fabric。 |
| 231 | - auto localDeviceId = peer->GetDeviceId(); | ||
| 232 | - | ||
| 233 | - // 3. 遍历所有rank节点,根据topoInstId创建fabric节点 | ||
| 234 | for (RankId rankId : rankIds) { | 469 | for (RankId rankId : rankIds) { |
| 235 | LocalId localId = rankGraph_->GetLocalId(rankId); | 470 | LocalId localId = rankGraph_->GetLocalId(rankId); |
| 471 | + const auto& levelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[rankId], 0); | ||
| 236 | auto peer2netEdges = phyTopoGraph->GetEdges(localId, PhyTopo::Fabric::GetId()); | 472 | auto peer2netEdges = phyTopoGraph->GetEdges(localId, PhyTopo::Fabric::GetId()); |
| 237 | 473 | ||
| 238 | HCCL_RUN_INFO( | 474 | HCCL_RUN_INFO( |
| @@ -240,47 +476,30 @@ void RankGraphBuilder::AddTopoDescFabricInfo() | |||
| 240 | rankId, localId, peer2netEdges.size()); | 476 | rankId, localId, peer2netEdges.size()); |
| 241 | 477 | ||
| 242 | for (const auto& link : peer2netEdges) { | 478 | for (const auto& link : peer2netEdges) { |
| 243 | - u32 topoInstId = link->GetTopoInstId(); | 479 | + if (link == nullptr || link->GetType() != LinkType::PEER2NET || link->GetSourceIFace() == nullptr) { |
| 244 | - auto topoType = link->GetTopoType(); | 480 | + continue; |
| 245 | - | ||
| 246 | - // 创建Fabric节点 | ||
| 247 | - if (fabNodes.find(topoInstId) == fabNodes.end()) { | ||
| 248 | - auto fabNodePtr = std::make_shared<NetInstance::Fabric>(topoInstId); | ||
| 249 | - innerNetInstance->AddNode(fabNodePtr); | ||
| 250 | - fabNodes[topoInstId] = fabNodePtr; | ||
| 251 | - HCCL_INFO( | ||
| 252 | - "[RankGraphBuilder][AddTopoDescFabricInfo] Created new Fabric node for topoInstId: %u", topoInstId); | ||
| 253 | } | 481 | } |
| 482 | + for (const auto& addrInfo : levelInfo.rankAddrs) { | ||
| 483 | + auto planeIter = planeId2Node.find(addrInfo.planeId); | ||
| 484 | + if (addrInfo.addr == IpAddress() || planeIter == planeId2Node.end() | ||
| 485 | + || !IsPeer2NetLinkMatched(link, addrInfo)) { | ||
| 486 | + continue; | ||
| 487 | + } | ||
| 254 | 488 | ||
| 255 | - // 获取 peer 节点 | 489 | + FabricId fabId = planeIter->second; |
| 256 | - auto peerNode = peers_.at(rankId); | 490 | + shared_ptr<NetInstance::Fabric> fabNode = fabNodes[fabId]; |
| 491 | + if (fabNode == nullptr) { | ||
| 492 | + fabNode = make_shared<NetInstance::Fabric>(fabId, addrInfo.planeId); | ||
| 493 | + innerNetInstance->AddNode(fabNode); | ||
| 494 | + fabNodes[fabId] = fabNode; | ||
| 495 | + HCCL_INFO( | ||
| 496 | + "[RankGraphBuilder][AddTopoDescFabricInfo] create Fabric for planeId[%s], " | ||
| 497 | + "fabricId[%u]", | ||
| 498 | + addrInfo.planeId.c_str(), fabId); | ||
| 499 | + } | ||
| 257 | 500 | ||
| 258 | - // 构造连接接口 | 501 | + const vector<shared_ptr<PhyTopo::Link>> matchedLinks = {link}; |
[LOW] AddTopoDescFabricInfo 每次 addrInfo 迭代创建临时 vector,嵌套循环中产生分配抖动 第 395 行 建议修复:
![]() ![]() | |||
| 259 | - auto peerIfaces = ConstructConnIFromPhyTopoConnIAndPortMap( | 502 | + AddPeer2NetLink(0, netInstId, rankId, addrInfo, fabNode, matchedLinks, false); |
| 260 | - link->GetSourceIFace(), peerNode->GetPortAddrMapLayer0(), topoType, topoInstId, localDeviceId); | ||
| 261 | - | ||
| 262 | - for (const auto& iface : peerIfaces) { | ||
| 263 | - peerNode->AddConnInterface(0, iface); | ||
| 264 | - } | ||
| 265 | - auto fabNodePtr = fabNodes[topoInstId]; | ||
| 266 | - // 构造 peer2netLink 和 net2peerLink(双向) | ||
| 267 | - for (const auto& iface : peerIfaces) { | ||
| 268 | - auto peer2netLink = std::make_shared<NetInstance::Link>( | ||
| 269 | - peerNode, fabNodePtr, iface, nullptr, LinkType::PEER2NET, link->GetLinkProtocols(), | ||
| 270 | - LinkDirection::BOTH, 2); | ||
| 271 | - | ||
| 272 | - auto net2peerLink = std::make_shared<NetInstance::Link>( | ||
| 273 | - fabNodePtr, peerNode, nullptr, iface, LinkType::PEER2NET, link->GetLinkProtocols(), | ||
| 274 | - LinkDirection::BOTH, 2); | ||
| 275 | - | ||
| 276 | - // 插入 link | ||
| 277 | - tempNetInsts_[0][netInstId]->AddLink(peer2netLink); | ||
| 278 | - tempNetInsts_[0][netInstId]->AddLink(net2peerLink); | ||
| 279 | - tempNetInsts_[0][netInstId]->UpdateTopoInst(topoInstId, topoType, rankId); | ||
| 280 | - HCCL_RUN_INFO( | ||
| 281 | - "[RankGraphBuilder][AddTopoDescFabricInfo] netLayer0 rankId[%u] netInstId[%s] Add Fabric " | ||
| 282 | - "Info success!", | ||
| 283 | - rankId, netInstId.c_str()); | ||
| 284 | } | 503 | } |
| 285 | } | 504 | } |
| 286 | } | 505 | } |
| @@ -299,21 +518,12 @@ std::map<PlaneId, FabricId> GetFabricsFromAddrInfo(const std::vector<AddressInfo | |||
| 299 | return planeId2FabricId; | 518 | return planeId2FabricId; |
| 300 | } | 519 | } |
| 301 | 520 | ||
| 302 | -void RankGraphBuilder::CheckNetLayerFromPhyTopo(const u32 netLayer) const | ||
| 303 | -{ | ||
| 304 | - if (!PhyTopo::GetInstance()->IsNetLayerExisted(netLayer)) { | ||
| 305 | - THROW<InvalidParamsException>(StringFormat( | ||
| 306 | - "[RankGraphBuilder][CheckNetLayerFromPhyTopo]" | ||
| 307 | - "netLayer[%u] not exist in topo.", | ||
| 308 | - netLayer)); | ||
| 309 | - } | ||
| 310 | -} | ||
| 311 | - | ||
| 312 | // 根据ranktable构造添加peers和NetInstances, NetInstance添加nodes和links(peer2net) | 521 | // 根据ranktable构造添加peers和NetInstances, NetInstance添加nodes和links(peer2net) |
| 313 | // 1. 创建NetInstance ( 每个NetInstance 添加 Rank, Node, Link); | 522 | // 1. 创建NetInstance ( 每个NetInstance 添加 Rank, Node, Link); |
| 314 | // 2. RankGraph中添加NetInstance, Peer, Fabric, | 523 | // 2. RankGraph中添加NetInstance, Peer, Fabric, |
| 315 | void RankGraphBuilder::BuildFromRankTable() | 524 | void RankGraphBuilder::BuildFromRankTable() |
| 316 | { | 525 | { |
| 526 | + peer2NetPhyLinksCache_.clear(); | ||
| 317 | // 保存NetInstance指针以便后续执行Add操作 | 527 | // 保存NetInstance指针以便后续执行Add操作 |
| 318 | tempNetInsts_.resize(MAX_NET_LAYER); // 为了方便修改RankGraph的NetInstance,共享指针。 | 528 | tempNetInsts_.resize(MAX_NET_LAYER); // 为了方便修改RankGraph的NetInstance,共享指针。 |
| 319 | 529 | ||
| @@ -329,8 +539,6 @@ void RankGraphBuilder::BuildFromRankTable() | |||
| 329 | 539 | ||
| 330 | // 构造当前rank的每个LevelInfo所在NetInstance, 添加 RankId 和 Peer | 540 | // 构造当前rank的每个LevelInfo所在NetInstance, 添加 RankId 和 Peer |
| 331 | for (const auto& levelInfo : rankInfo.rankLevelInfos) { | 541 | for (const auto& levelInfo : rankInfo.rankLevelInfos) { |
| 332 | - // 校验netLayer是否在topo中 | ||
| 333 | - CheckNetLayerFromPhyTopo(levelInfo.netLayer); | ||
| 334 | // rankLevelInfo.level、id对应NetInstance,若不存在则创建 | 542 | // rankLevelInfo.level、id对应NetInstance,若不存在则创建 |
| 335 | auto curNetInstance = GetOrCreateNetInstance( | 543 | auto curNetInstance = GetOrCreateNetInstance( |
| 336 | levelInfo.netLayer, levelInfo.netInstId, levelInfo.netType, tempNetInsts_, rankGraph_.get()); | 544 | levelInfo.netLayer, levelInfo.netInstId, levelInfo.netType, tempNetInsts_, rankGraph_.get()); |
| @@ -379,6 +587,18 @@ void RankGraphBuilder::SetEndpointDesc() | |||
| 379 | for (const auto& layer : layers) { | 587 | for (const auto& layer : layers) { |
| 380 | auto ifacesVec = peer->GetIfacesByLayer(layer); | 588 | auto ifacesVec = peer->GetIfacesByLayer(layer); |
| 381 | for (const auto& iface : ifacesVec) { | 589 | for (const auto& iface : ifacesVec) { |
| 590 | + const auto& ports = iface->GetPorts(); | ||
| 591 | + std::string portsStr; | ||
| 592 | + for (auto portIter = ports.begin(); portIter != ports.end(); ++portIter) { | ||
| 593 | + if (portIter != ports.begin()) { | ||
| 594 | + portsStr += ","; | ||
| 595 | + } | ||
| 596 | + portsStr += *portIter; | ||
| 597 | + } | ||
| 598 | + HCCL_INFO( | ||
| 599 | + "[RankGraphBuilder::SetEndpointDesc] layer[%u] topoInstId[%u] bwCoeff[%zu] ports[%s]", layer, | ||
| 600 | + iface->GetTopoInstId(), ports.size(), portsStr.c_str()); | ||
| 601 | + | ||
| 382 | const auto& protocols = iface->GetLinkProtocols(); | 602 | const auto& protocols = iface->GetLinkProtocols(); |
| 383 | for (const auto& protocol : protocols) { | 603 | for (const auto& protocol : protocols) { |
| 384 | EndpointDesc desc{}; | 604 | EndpointDesc desc{}; |
| @@ -394,7 +614,7 @@ void RankGraphBuilder::SetEndpointDesc() | |||
| 394 | HCCL_INFO( | 614 | HCCL_INFO( |
| 395 | "[RankGraphBuilder::SetEndpointDesc] local type[%d] protocol[%d]", desc.loc.locType, desc.protocol); | 615 | "[RankGraphBuilder::SetEndpointDesc] local type[%d] protocol[%d]", desc.loc.locType, desc.protocol); |
| 396 | 616 | ||
| 397 | - peer->SetEndpointToIface(desc.commAddr, desc.protocol, iface); | 617 | + peer->SetEndpointToIface(layer, iface->GetTopoInstId(), desc.commAddr, desc.protocol, iface); |
| 398 | } | 618 | } |
| 399 | } | 619 | } |
| 400 | } | 620 | } |
| @@ -434,7 +654,7 @@ std::shared_ptr<NetInstance> RankGraphBuilder::CreateNetInstance(const RankLevel | |||
| 434 | // 从phytopo和ranktable中读取数据共同构建peer2peer的边。 | 654 | // 从phytopo和ranktable中读取数据共同构建peer2peer的边。 |
| 435 | void RankGraphBuilder::BuildPeer2PeerLinks() | 655 | void RankGraphBuilder::BuildPeer2PeerLinks() |
| 436 | { | 656 | { |
| 437 | - auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0); | 657 | + auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(); |
| 438 | if (phyTopoGraph == nullptr) { | 658 | if (phyTopoGraph == nullptr) { |
| 439 | THROW<NullPtrException>(StringFormat("[RankGraphBuilder][BuildPeer2PeerLinks] phyTopoGraph is nullptr")); | 659 | THROW<NullPtrException>(StringFormat("[RankGraphBuilder][BuildPeer2PeerLinks] phyTopoGraph is nullptr")); |
| 440 | } | 660 | } |
| @@ -445,8 +665,7 @@ void RankGraphBuilder::BuildPeer2PeerLinks() | |||
| 445 | } | 665 | } |
| 446 | set<RankId> rankIds = innerNetInstance->GetRankIds(); | 666 | set<RankId> rankIds = innerNetInstance->GetRankIds(); |
| 447 | 667 | ||
| 448 | - auto peer = rankGraph_->GetPeer(rankGraph_->GetMyRank()); | 668 | + auto localDeviceId = GetLocalDeviceId(); |
| 449 | - auto localDeviceId = peer->GetDeviceId(); | ||
| 450 | for (const auto srcRankId : rankIds) { | 669 | for (const auto srcRankId : rankIds) { |
| 451 | for (const auto dstRankId : rankIds) { | 670 | for (const auto dstRankId : rankIds) { |
| 452 | if (srcRankId == dstRankId) { | 671 | if (srcRankId == dstRankId) { |
| @@ -462,7 +681,7 @@ void RankGraphBuilder::BuildPeer2PeerLinks() | |||
| 462 | 681 | ||
| 463 | std::vector<shared_ptr<PhyTopo::Link>> phyLinks | 682 | std::vector<shared_ptr<PhyTopo::Link>> phyLinks |
| 464 | = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId); | 683 | = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId); |
| 465 | - // 根据ports在ranktable找对对应的地址,几个地址就有几条link。 | 684 | + // 按 RankTable layer 0 端口筛选物理 P2P 边并补齐地址。 |
| 466 | 685 | ||
| 467 | shared_ptr<NetInstance::Peer> srcPeer = peers_.at(srcRankId); | 686 | shared_ptr<NetInstance::Peer> srcPeer = peers_.at(srcRankId); |
| 468 | shared_ptr<NetInstance::Peer> dstPeer = peers_.at(dstRankId); | 687 | shared_ptr<NetInstance::Peer> dstPeer = peers_.at(dstRankId); |
| @@ -505,7 +724,8 @@ void RankGraphBuilder::UpdateTopoInstForMyRankOnly() | |||
| 505 | auto netInstId = innerNetInstance->GetNetInstId(); | 724 | auto netInstId = innerNetInstance->GetNetInstId(); |
| 506 | set<RankId> rankIds = innerNetInstance->GetRankIds(); | 725 | set<RankId> rankIds = innerNetInstance->GetRankIds(); |
| 507 | 726 | ||
| 508 | - auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0); | 727 | + auto localDeviceId = GetLocalDeviceId(); |
| 728 | + auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(); | ||
| 509 | if (phyTopoGraph == nullptr) { | 729 | if (phyTopoGraph == nullptr) { |
| 510 | THROW<NullPtrException>( | 730 | THROW<NullPtrException>( |
| 511 | StringFormat("[RankGraphBuilder][UpdateTopoInstForMyRankOnly] phyTopoGraph is nullptr")); | 731 | StringFormat("[RankGraphBuilder][UpdateTopoInstForMyRankOnly] phyTopoGraph is nullptr")); |
| @@ -520,20 +740,34 @@ void RankGraphBuilder::UpdateTopoInstForMyRankOnly() | |||
| 520 | for (const auto srcRankId : rankIds) { | 740 | for (const auto srcRankId : rankIds) { |
| 521 | for (const auto dstRankId : rankIds) { | 741 | for (const auto dstRankId : rankIds) { |
| 522 | // 只处理涉及 myRank_ 的边 | 742 | // 只处理涉及 myRank_ 的边 |
| 523 | - if (srcRankId != myRank_ && dstRankId != myRank_) { | 743 | + if (srcRankId == dstRankId || (srcRankId != myRank_ && dstRankId != myRank_)) { |
| 524 | continue; | 744 | continue; |
| 525 | } | 745 | } |
| 526 | 746 | ||
| 527 | LocalId srcLocalId = rankGraph_->GetLocalId(srcRankId); | 747 | LocalId srcLocalId = rankGraph_->GetLocalId(srcRankId); |
| 528 | LocalId dstLocalId = rankGraph_->GetLocalId(dstRankId); | 748 | LocalId dstLocalId = rankGraph_->GetLocalId(dstRankId); |
| 749 | + if (srcLocalId == BACKUP_LOCAL_ID || dstLocalId == BACKUP_LOCAL_ID) { | ||
| 750 | + continue; | ||
| 751 | + } | ||
| 529 | 752 | ||
| 530 | std::vector<shared_ptr<PhyTopo::Link>> phyLinks | 753 | std::vector<shared_ptr<PhyTopo::Link>> phyLinks |
| 531 | = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId); | 754 | = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId); |
| 755 | + // 通过 RankTable layer 0 端口映射物理 P2P 链路。 | ||
| 756 | + const auto& srcLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[srcRankId], 0); | ||
| 757 | + const auto& dstLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[dstRankId], 0); | ||
| 532 | 758 | ||
| 533 | for (shared_ptr<PhyTopo::Link> phyLink : phyLinks) { | 759 | for (shared_ptr<PhyTopo::Link> phyLink : phyLinks) { |
| 534 | - u32 topoInstId = phyLink->GetTopoInstId(); | 760 | + auto sourceIfaces = ConstructConnIFromPhyTopoConnIAndPortMap( |
[MEDIUM] UpdateTopoInstForMyRankOnly 构造 ConnInterface 后丢弃,仅为空检查触发无意义分配与系统调用 第 626-636 行在 问题分析:
建议修复: 用一个轻量的端口匹配检查替代完整 ConnInterface 构造:
![]() ![]() | |||
| 535 | - auto topoType = phyLink->GetTopoType(); | 761 | + phyLink->GetSourceIFace(), srcLevelInfo.portAddrMap, phyLink->GetTopoType(), |
| 536 | - tempNetInsts_[0][netInstId]->UpdateTopoInst(topoInstId, topoType, dstRankId); | 762 | + phyLink->GetTopoInstId(), localDeviceId); |
| 763 | + auto targetIfaces = ConstructConnIFromPhyTopoConnIAndPortMap( | ||
| 764 | + phyLink->GetTargetIFace(), dstLevelInfo.portAddrMap, phyLink->GetTopoType(), | ||
| 765 | + phyLink->GetTopoInstId(), localDeviceId); | ||
| 766 | + if (sourceIfaces.empty() || targetIfaces.empty()) { | ||
| 767 | + continue; | ||
| 768 | + } | ||
| 769 | + tempNetInsts_[0][netInstId]->UpdateTopoInst( | ||
| 770 | + phyLink->GetTopoInstId(), phyLink->GetTopoType(), dstRankId); | ||
| 537 | } | 771 | } |
| 538 | } | 772 | } |
| 539 | } | 773 | } |
| @@ -547,6 +781,7 @@ std::vector<std::shared_ptr<NetInstance::ConnInterface>> ConstructConnIFromPhyTo | |||
| 547 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> netConnIFaces; | 781 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> netConnIFaces; |
| 548 | std::set<string> phyPorts = phyConnIFace->GetPorts(); | 782 | std::set<string> phyPorts = phyConnIFace->GetPorts(); |
| 549 | std::map<IpAddress, std::set<string>> addr2Ports; | 783 | std::map<IpAddress, std::set<string>> addr2Ports; |
| 784 | + // 非 PCIe 端口仅保留 RankTable 中存在的物理端口。 | ||
| 550 | for (auto port : phyPorts) { | 785 | for (auto port : phyPorts) { |
| 551 | if (*(phyConnIFace->GetLinkProtocols().begin()) == LinkProtocol::PCIE) { | 786 | if (*(phyConnIFace->GetLinkProtocols().begin()) == LinkProtocol::PCIE) { |
| 552 | IpAddress tempIp; | 787 | IpAddress tempIp; |
| @@ -623,7 +858,7 @@ std::vector<std::shared_ptr<PhyTopo::Link>> GetPeer2PeerPhyLinks( | |||
| 623 | NodeId dstNodeId = PhyTopo::Peer::GetId(dstLocalId); | 858 | NodeId dstNodeId = PhyTopo::Peer::GetId(dstLocalId); |
| 624 | 859 | ||
| 625 | phyTopoGraph->TraverseEdge(srcNodeId, dstNodeId, [&](shared_ptr<PhyTopo::Link> link) { | 860 | phyTopoGraph->TraverseEdge(srcNodeId, dstNodeId, [&](shared_ptr<PhyTopo::Link> link) { |
| 626 | - if (link != nullptr) { | 861 | + if (link != nullptr && link->GetType() == LinkType::PEER2PEER) { |
| 627 | links.push_back(link); | 862 | links.push_back(link); |
| 628 | } | 863 | } |
| 629 | }); | 864 | }); |
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | + | ||
| 16 | 17 | ||
| 17 | 18 | ||
| 18 | 19 | ||
| @@ -42,28 +43,33 @@ private: | |||
| 42 | std::unique_ptr<RankGraph> rankGraph_; | 43 | std::unique_ptr<RankGraph> rankGraph_; |
| 43 | RankId2PeerMap peers_; | 44 | RankId2PeerMap peers_; |
| 44 | Level2Id2NetInst tempNetInsts_; | 45 | Level2Id2NetInst tempNetInsts_; |
| 46 | + std::map<LocalId, std::vector<std::shared_ptr<PhyTopo::Link>>> peer2NetPhyLinksCache_; | ||
| 45 | RankId myRank_; | 47 | RankId myRank_; |
| 46 | std::shared_ptr<TopoInfo> topoInfo_; | 48 | std::shared_ptr<TopoInfo> topoInfo_; |
| 47 | UpdaterFor64Plus1 updaterFor64Plus1_{}; | 49 | UpdaterFor64Plus1 updaterFor64Plus1_{}; |
| 48 | 50 | ||
| 49 | void CheckMyRankInRankTable() const; | 51 | void CheckMyRankInRankTable() const; |
| 50 | - void CheckNetLayerFromPhyTopo(const u32 netLayer) const; | ||
| 51 | void BuildRankGraph(); | 52 | void BuildRankGraph(); |
| 52 | void BuildFromRankTable(); | 53 | void BuildFromRankTable(); |
| 53 | void BuildPeer2PeerLinks(); | 54 | void BuildPeer2PeerLinks(); |
| 54 | void AddFabricInfo(u32 level); | 55 | void AddFabricInfo(u32 level); |
| 56 | + LinkProtocol ResolveUbProtocolByEid(const AddressInfo& addrInfo, bool& supportsRtp) const; | ||
| 57 | + std::map<PlaneId, LinkProtocol> ResolvePlaneUbProtocols(u32 netLayer, std::set<PlaneId>& ctpRtpPlanes); | ||
| 58 | + const std::vector<std::shared_ptr<PhyTopo::Link>>& GetPeer2NetPhyLinksCached(LocalId localId); | ||
| 55 | void AddPeer2NetLink( | 59 | void AddPeer2NetLink( |
| 56 | const u32 netLayer, const std::string& netInstId, RankId rankId, const AddressInfo& addrInfo, | 60 | const u32 netLayer, const std::string& netInstId, RankId rankId, const AddressInfo& addrInfo, |
| 57 | - const std::shared_ptr<NetInstance::Fabric>& fabNode, const std::vector<std::shared_ptr<PhyTopo::Link>>& links); | 61 | + const std::shared_ptr<NetInstance::Fabric>& fabNode, |
| 62 | + const std::vector<std::shared_ptr<PhyTopo::Link>>& matchedLinks, bool exposeUbTp); | ||
| 58 | void AddTopoDescFabricInfo(); | 63 | void AddTopoDescFabricInfo(); |
| 59 | void UpdateTopoInstForMyRankOnly(); | 64 | void UpdateTopoInstForMyRankOnly(); |
| 65 | + u32 GetLocalDeviceId() const; | ||
| 60 | const RankLevelInfo& GetRankLevelInfoByNetLayer(const NewRankInfo& rankInfo, u32 netLayer) const; | 66 | const RankLevelInfo& GetRankLevelInfoByNetLayer(const NewRankInfo& rankInfo, u32 netLayer) const; |
| 61 | std::shared_ptr<NetInstance> GetNetInstance(const RankLevelInfo& levelInfo); | 67 | std::shared_ptr<NetInstance> GetNetInstance(const RankLevelInfo& levelInfo); |
| 62 | std::shared_ptr<NetInstance> CreateNetInstance(const RankLevelInfo& levelInfo); | 68 | std::shared_ptr<NetInstance> CreateNetInstance(const RankLevelInfo& levelInfo); |
| 63 | }; | 69 | }; |
| 64 | 70 | ||
| 65 | std::map<PlaneId, FabricId> GetFabricsFromAddrInfo(const std::vector<AddressInfo>& rankAddrs); | 71 | std::map<PlaneId, FabricId> GetFabricsFromAddrInfo(const std::vector<AddressInfo>& rankAddrs); |
| 66 | -std::vector<std::shared_ptr<PhyTopo::Link>> GetPeer2NetPhyLinks(u32 netLayer, LocalId localId); | 72 | +std::vector<std::shared_ptr<PhyTopo::Link>> GetPeer2NetPhyLinks(LocalId localId); |
| 67 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> ConstructConnIFromPhyTopoConnIAndPortMap( | 73 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> ConstructConnIFromPhyTopoConnIAndPortMap( |
| 68 | std::shared_ptr<PhyTopo::ConnInterface> phyConnIFace, | 74 | std::shared_ptr<PhyTopo::ConnInterface> phyConnIFace, |
| 69 | const std::map<std::string, std::vector<IpAddress>>& portAddrMap, const TopoType topoType, const u32 topoInstId, | 75 | const std::map<std::string, std::vector<IpAddress>>& portAddrMap, const TopoType topoType, const u32 topoInstId, |
| @@ -8,6 +8,8 @@ | |||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | 8 | * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | + | ||
| 12 | + | ||
| 11 | 13 | ||
| 12 | 14 | ||
| 13 | 15 | ||
| @@ -17,6 +19,40 @@ namespace Hccl { | |||
| 17 | 19 | ||
| 18 | using namespace std; | 20 | using namespace std; |
| 19 | 21 | ||
| 22 | +namespace { | ||
| 23 | + | ||
| 24 | + bool HasLayer0Port(const shared_ptr<NetInstance::Peer>& peer, const set<string>& ports) | ||
| 25 | + { | ||
| 26 | + if (peer == nullptr || ports.empty()) { | ||
| 27 | + return false; | ||
| 28 | + } | ||
| 29 | + IpAddress addr; | ||
| 30 | + return any_of(ports.begin(), ports.end(), [&peer, &addr](const string& port) { | ||
| 31 | + return peer->TryGetLayer0Address(port, addr); | ||
| 32 | + }); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + bool HasLayer0Peer2PeerLink( | ||
| 36 | + const shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>>& phyTopoGraph, const shared_ptr<NetInstance::Peer>& peer, | ||
| 37 | + LocalId replacedLocalId) | ||
| 38 | + { | ||
| 39 | + if (phyTopoGraph == nullptr || peer == nullptr) { | ||
| 40 | + return false; | ||
| 41 | + } | ||
| 42 | + bool matched = false; | ||
| 43 | + phyTopoGraph->TraverseEdge( | ||
| 44 | + PhyTopo::Peer::GetId(peer->GetLocalId()), PhyTopo::Peer::GetId(replacedLocalId), | ||
| 45 | + [&peer, &matched](const shared_ptr<PhyTopo::Link>& link) { | ||
| 46 | + if (link == nullptr || link->GetType() != LinkType::PEER2PEER || link->GetSourceIFace() == nullptr) { | ||
| 47 | + return; | ||
| 48 | + } | ||
| 49 | + matched = matched || HasLayer0Port(peer, link->GetSourceIFace()->GetPorts()); | ||
| 50 | + }); | ||
| 51 | + return matched; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | +} // namespace | ||
| 55 | + | ||
| 20 | void UpdaterFor64Plus1::SaveReplaceInfo(const NewRankInfo& rank) | 56 | void UpdaterFor64Plus1::SaveReplaceInfo(const NewRankInfo& rank) |
| 21 | { | 57 | { |
| 22 | if (rank.localId != BACKUP_LOCAL_ID) { | 58 | if (rank.localId != BACKUP_LOCAL_ID) { |
| @@ -72,7 +108,7 @@ void UpdaterFor64Plus1::UpdateNetInstance( | |||
| 72 | if (netInstance == nullptr) { | 108 | if (netInstance == nullptr) { |
| 73 | THROW<NullPtrException>(StringFormat("[UpdaterFor64Plus1][%s] netInstance is nullptr", __func__)); | 109 | THROW<NullPtrException>(StringFormat("[UpdaterFor64Plus1][%s] netInstance is nullptr", __func__)); |
| 74 | } | 110 | } |
| 75 | - auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0); | 111 | + auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(); |
| 76 | if (phyTopoGraph == nullptr) { | 112 | if (phyTopoGraph == nullptr) { |
| 77 | THROW<NullPtrException>(StringFormat("[UpdaterFor64Plus1][%s] phyTopoGraph is nullptr", __func__)); | 113 | THROW<NullPtrException>(StringFormat("[UpdaterFor64Plus1][%s] phyTopoGraph is nullptr", __func__)); |
| 78 | } | 114 | } |
| @@ -92,7 +128,7 @@ void UpdaterFor64Plus1::UpdateNetInstance( | |||
| 92 | if (!IsSameX(peer->GetLocalId(), replacedLocalId) && !IsSameY(peer->GetLocalId(), replacedLocalId)) { | 128 | if (!IsSameX(peer->GetLocalId(), replacedLocalId) && !IsSameY(peer->GetLocalId(), replacedLocalId)) { |
| 93 | continue; | 129 | continue; |
| 94 | } | 130 | } |
| 95 | - if (!phyTopoGraph->HasEdge(PhyTopo::Peer::GetId(peer->GetLocalId()), PhyTopo::Peer::GetId(replacedLocalId))) { | 131 | + if (!HasLayer0Peer2PeerLink(phyTopoGraph, peer, replacedLocalId)) { |
| 96 | continue; | 132 | continue; |
| 97 | } | 133 | } |
| 98 | backupLinkedPeers.emplace_back(peer); | 134 | backupLinkedPeers.emplace_back(peer); |
| @@ -108,16 +144,7 @@ void UpdaterFor64Plus1::AddPeer2BackupLinks( | |||
| 108 | shared_ptr<NetInstance::Peer> peer, shared_ptr<NetInstance::Peer> backupPeer, LocalId replacedLocalId, | 144 | shared_ptr<NetInstance::Peer> peer, shared_ptr<NetInstance::Peer> backupPeer, LocalId replacedLocalId, |
| 109 | NetInstance* netInstance, [[maybe_unused]] const RankTableInfo* rankTable) const | 145 | NetInstance* netInstance, [[maybe_unused]] const RankTableInfo* rankTable) const |
| 110 | { | 146 | { |
| 111 | - auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0); | 147 | + auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(); |
| 112 | - | ||
| 113 | - std::unordered_map<u64, u64> fabricIds; | ||
| 114 | - auto peer2AllPlaneEdges | ||
| 115 | - = phyTopoGraph->GetEdges(PhyTopo::Peer::GetId(backupPeer->GetLocalId()), PhyTopo::Fabric::GetId()); | ||
| 116 | - for (auto edge : peer2AllPlaneEdges) { | ||
| 117 | - auto topoInstId = edge->GetTopoInstId(); | ||
| 118 | - auto fabricId = static_cast<u64>(topoInstId) | (static_cast<u64>(1) << 32); | ||
| 119 | - fabricIds[topoInstId] = fabricId; | ||
| 120 | - } | ||
| 121 | 148 | ||
| 122 | auto idx = GetLinkIndex(peer->GetLocalId(), replacedLocalId); | 149 | auto idx = GetLinkIndex(peer->GetLocalId(), replacedLocalId); |
| 123 | auto backupPlaneId = idx.first; | 150 | auto backupPlaneId = idx.first; |
| @@ -129,8 +156,10 @@ void UpdaterFor64Plus1::AddPeer2BackupLinks( | |||
| 129 | // 先获取phyTopoGraph中备份面和备份D的连接,因为只有一个fabric,所以会获取到全量16条备份面和备份D的连接 | 156 | // 先获取phyTopoGraph中备份面和备份D的连接,因为只有一个fabric,所以会获取到全量16条备份面和备份D的连接 |
| 130 | // Edges中可能包含多个连接,但是在phytopo中保存为一条连接,内部有多个连接的端口 | 157 | // Edges中可能包含多个连接,但是在phytopo中保存为一条连接,内部有多个连接的端口 |
| 131 | // 拿到物理边后,根据backupPlaneId匹配,选择对应的一条物理边 | 158 | // 拿到物理边后,根据backupPlaneId匹配,选择对应的一条物理边 |
| 132 | - std::shared_ptr<PhyTopo::Link> backD2PlaneEdges = GetPeer2PlaneEdges(backupPlaneId, backupPeer, phyTopoGraph); | 159 | + std::shared_ptr<PhyTopo::Link> backD2PlaneEdges |
| 133 | - std::shared_ptr<PhyTopo::Link> peer2PlaneEdges = GetPeer2PlaneEdges(backupPlaneId, peer, phyTopoGraph); | 160 | + = GetPeer2PlaneEdges(backupPlaneId, backupPeer, phyTopoGraph, BACKUP_TO_PLANE_ADDR_NUM); |
| 161 | + std::shared_ptr<PhyTopo::Link> peer2PlaneEdges | ||
| 162 | + = GetPeer2PlaneEdges(backupPlaneId, peer, phyTopoGraph, 1, backD2PlaneEdges->GetLinkProtocols()); | ||
| 134 | 163 | ||
| 135 | // 取得端口列表,根据backupLinkIdx去选择对应的端口 | 164 | // 取得端口列表,根据backupLinkIdx去选择对应的端口 |
| 136 | std::set<std::string> backD2PlanePorts = backD2PlaneEdges->GetSourceIFace()->GetPorts(); | 165 | std::set<std::string> backD2PlanePorts = backD2PlaneEdges->GetSourceIFace()->GetPorts(); |
| @@ -151,10 +180,14 @@ void UpdaterFor64Plus1::AddPeer2BackupLinks( | |||
| 151 | std::string backD2PlanePort = GetPortFromSet(backD2PlanePorts, backupLinkIdx); | 180 | std::string backD2PlanePort = GetPortFromSet(backD2PlanePorts, backupLinkIdx); |
| 152 | std::string peer2PlanePort = GetPortFromSet(peer2PlanePorts, 0); | 181 | std::string peer2PlanePort = GetPortFromSet(peer2PlanePorts, 0); |
| 153 | 182 | ||
| 154 | - // 匹配了对应的端口后,去ranktableinfo中查对应端口的地址信息 | 183 | + // 最终选中的端口必须能在 RankTable layer 0 中找到地址。 |
| 155 | - // todo 加一下peer->GetPortAddrMapLayer0()是否能找到port对应的地址。 | 184 | + IpAddress backD2PlaneAddr; |
| 156 | - IpAddress backD2PlaneAddr = backupPeer->GetPortAddrMapLayer0()[backD2PlanePort][0]; | 185 | + IpAddress peer2PlaneAddr; |
| 157 | - IpAddress peer2PlaneAddr = peer->GetPortAddrMapLayer0()[peer2PlanePort][0]; | 186 | + if (backupPeer == nullptr || peer == nullptr || !backupPeer->TryGetLayer0Address(backD2PlanePort, backD2PlaneAddr) |
| 187 | + || !peer->TryGetLayer0Address(peer2PlanePort, peer2PlaneAddr)) { | ||
| 188 | + THROW<InvalidParamsException>( | ||
| 189 | + StringFormat("[UpdaterFor64Plus1][%s] selected port does not belong to layer0", __func__)); | ||
| 190 | + } | ||
| 158 | 191 | ||
| 159 | // 组装成NetInstance的conninterface,加入peer和backupPeer | 192 | // 组装成NetInstance的conninterface,加入peer和backupPeer |
| 160 | if (backD2PlaneEdges->GetSourceIFace() == nullptr || peer2PlaneEdges->GetSourceIFace() == nullptr) { | 193 | if (backD2PlaneEdges->GetSourceIFace() == nullptr || peer2PlaneEdges->GetSourceIFace() == nullptr) { |
| @@ -182,29 +215,44 @@ void UpdaterFor64Plus1::AddPeer2BackupLinks( | |||
| 182 | backupPeer, peer, backupIface, peerIface, LinkType::PEER2PEER, backD2PlaneEdges->GetLinkProtocols()); | 215 | backupPeer, peer, backupIface, peerIface, LinkType::PEER2PEER, backD2PlaneEdges->GetLinkProtocols()); |
| 183 | netInstance->AddLink(backup2Peer); | 216 | netInstance->AddLink(backup2Peer); |
| 184 | 217 | ||
| 185 | - // peer2peer建立后删除graph中DB到所选planeId的对应的peer2net链路 | 218 | + // 删除备份 D 到所有 Fabric 的链路;Fabric 由 planeId 生成,不能用 topoInstId 推导节点 ID。 |
| 186 | - // 直接删除备份d和fabric的链接保证GetLinks接口只能获取到peer2db的一条peer2peer | 219 | + for (const auto& fabric : netInstance->GetFabrics()) { |
| 187 | - // 删除peer到fabric用到的peer2net | 220 | + if (fabric == nullptr) { |
| 188 | - for (auto id : fabricIds) { | 221 | + continue; |
| 189 | - netInstance->DeleteLink(backupPeer->GetNodeId(), id.second); | 222 | + } |
| 223 | + netInstance->DeleteLink(backupPeer->GetNodeId(), fabric->GetNodeId()); | ||
| 190 | } | 224 | } |
| 191 | } | 225 | } |
| 192 | 226 | ||
| 193 | std::shared_ptr<PhyTopo::Link> UpdaterFor64Plus1::GetPeer2PlaneEdges( | 227 | std::shared_ptr<PhyTopo::Link> UpdaterFor64Plus1::GetPeer2PlaneEdges( |
| 194 | u32 backupPlaneId, shared_ptr<NetInstance::Peer> peer, | 228 | u32 backupPlaneId, shared_ptr<NetInstance::Peer> peer, |
| 195 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyTopoGraph) const | 229 | + std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyTopoGraph, u32 expectedPortNum, |
| 230 | + const std::set<LinkProtocol>& expectedProtocols) const | ||
| 196 | { | 231 | { |
| 197 | std::shared_ptr<PhyTopo::Link> peer2PlaneEdges = nullptr; | 232 | std::shared_ptr<PhyTopo::Link> peer2PlaneEdges = nullptr; |
| 198 | auto peer2AllPlaneEdges | 233 | auto peer2AllPlaneEdges |
| 199 | = phyTopoGraph->GetEdges(PhyTopo::Peer::GetId(peer->GetLocalId()), PhyTopo::Fabric::GetId()); | 234 | = phyTopoGraph->GetEdges(PhyTopo::Peer::GetId(peer->GetLocalId()), PhyTopo::Fabric::GetId()); |
| 200 | - if (peer2AllPlaneEdges.size() != BACKUP_PLANE_NUM) { | 235 | + std::set<u32> backupPlaneIds; |
| 201 | - THROW<InvalidParamsException>("[UpdaterFor64Plus1][%s] BackupPlane num error", __func__); | 236 | + for (const auto& edge : peer2AllPlaneEdges) { |
| 202 | - } | 237 | + // 按物理属性统计合法备份面,避免 RankTable 仅提供部分备份端口时漏计。 |
| 203 | - for (auto& edges : peer2AllPlaneEdges) { | 238 | + if (edge == nullptr || edge->GetType() != LinkType::PEER2NET || edge->GetSourceIFace() == nullptr |
| 204 | - if (edges->GetTopoInstId() == backupPlaneId) { | 239 | + || edge->GetSourceIFace()->GetPorts().size() != expectedPortNum |
| 205 | - peer2PlaneEdges = edges; | 240 | + || (!expectedProtocols.empty() && edge->GetLinkProtocols() != expectedProtocols) |
| 206 | - break; | 241 | + || edge->GetTopoInstId() >= BACKUP_PLANE_NUM) { |
| 242 | + continue; | ||
| 207 | } | 243 | } |
| 244 | + backupPlaneIds.insert(edge->GetTopoInstId()); | ||
| 245 | + // 真正选中的边必须命中 RankTable layer 0 端口。 | ||
| 246 | + if (edge->GetTopoInstId() == backupPlaneId && HasLayer0Port(peer, edge->GetSourceIFace()->GetPorts())) { | ||
| 247 | + if (peer2PlaneEdges != nullptr) { | ||
| 248 | + THROW<InvalidParamsException>( | ||
| 249 | + "[UpdaterFor64Plus1][%s] BackupPlane[%u] is ambiguous", __func__, backupPlaneId); | ||
| 250 | + } | ||
| 251 | + peer2PlaneEdges = edge; | ||
| 252 | + } | ||
| 253 | + } | ||
| 254 | + if (backupPlaneIds.size() != BACKUP_PLANE_NUM) { | ||
| 255 | + THROW<InvalidParamsException>("[UpdaterFor64Plus1][%s] BackupPlane num error", __func__); | ||
| 208 | } | 256 | } |
| 209 | if (peer2PlaneEdges == nullptr) { | 257 | if (peer2PlaneEdges == nullptr) { |
| 210 | THROW<NullPtrException>(StringFormat("[UpdaterFor64Plus1][%s] peer2PlaneEdges is nullptr", __func__)); | 258 | THROW<NullPtrException>(StringFormat("[UpdaterFor64Plus1][%s] peer2PlaneEdges is nullptr", __func__)); |
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | + | ||
| 17 | 18 | ||
| 18 | 19 | ||
| 19 | 20 | ||
| @@ -41,7 +42,8 @@ private: | |||
| 41 | std::string GetPortFromSet(std::set<string>& ports, u32 linkIdx) const; | 42 | std::string GetPortFromSet(std::set<string>& ports, u32 linkIdx) const; |
| 42 | std::shared_ptr<PhyTopo::Link> GetPeer2PlaneEdges( | 43 | std::shared_ptr<PhyTopo::Link> GetPeer2PlaneEdges( |
| 43 | u32 backupPlaneId, shared_ptr<NetInstance::Peer> peer, | 44 | u32 backupPlaneId, shared_ptr<NetInstance::Peer> peer, |
| 44 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyTopoGraph) const; | 45 | + std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyTopoGraph, u32 expectedPortNum, |
| 46 | + const std::set<LinkProtocol>& expectedProtocols = {}) const; | ||
| 45 | void AddPeer2BackupLinks( | 47 | void AddPeer2BackupLinks( |
| 46 | std::shared_ptr<NetInstance::Peer> peer, std::shared_ptr<NetInstance::Peer> backupPeer, LocalId replacedLocalId, | 48 | std::shared_ptr<NetInstance::Peer> peer, std::shared_ptr<NetInstance::Peer> backupPeer, LocalId replacedLocalId, |
| 47 | NetInstance* netInstance, const RankTableInfo* rankTable) const; | 49 | NetInstance* netInstance, const RankTableInfo* rankTable) const; |
| @@ -42,13 +42,7 @@ const unordered_map<string, AddrPosition> EdgeInfo::strToAddrPosition | |||
| 42 | 42 | ||
| 43 | void EdgeInfo::Deserialize(const nlohmann::json& edgeInfoJson) | 43 | void EdgeInfo::Deserialize(const nlohmann::json& edgeInfoJson) |
| 44 | { | 44 | { |
| 45 | - std::string msgNetLayer = "[EdgeInfo::Deserialize] error occurs when parser object of propName \"net_layer\""; | 45 | + // net_layer 不再解析,物理边只保留连接属性。 |
| 46 | - TRY_CATCH_THROW(InvalidParamsException, msgNetLayer, netLayer = GetJsonPropertyUInt(edgeInfoJson, "net_layer");); | ||
| 47 | - if (netLayer > MAX_VALUE_LEVEL) { | ||
| 48 | - THROW<InvalidParamsException>(StringFormat( | ||
| 49 | - "[EdgeInfo::%s] netLayer value[%u] is out of range[0, %u].", __func__, netLayer, MAX_VALUE_LEVEL)); | ||
| 50 | - } | ||
| 51 | - | ||
| 52 | DeserializeProtocol(edgeInfoJson); | 46 | DeserializeProtocol(edgeInfoJson); |
| 53 | 47 | ||
| 54 | if (edgeInfoJson.contains("topo_type")) { | 48 | if (edgeInfoJson.contains("topo_type")) { |
| @@ -174,9 +168,8 @@ void EdgeInfo::DeserializePort(const nlohmann::json& edgeInfoJson, std::string p | |||
| 174 | 168 | ||
| 175 | bool EdgeInfo::operator==(const EdgeInfo& other) const | 169 | bool EdgeInfo::operator==(const EdgeInfo& other) const |
| 176 | { | 170 | { |
| 177 | - return netLayer == other.netLayer && linkType == other.linkType && protocols == other.protocols | 171 | + return linkType == other.linkType && protocols == other.protocols && topoType == other.topoType |
| 178 | - && topoType == other.topoType && topoInstId == other.topoInstId && CompareEndpoints(other) | 172 | + && topoInstId == other.topoInstId && CompareEndpoints(other) && position == other.position; |
| 179 | - && position == other.position; | ||
| 180 | } | 173 | } |
| 181 | 174 | ||
| 182 | // 比较EndpointA和B | 175 | // 比较EndpointA和B |
| @@ -255,7 +248,6 @@ std::string EdgeInfo::Describe() const | |||
| 255 | string localBPortsStr = DescribePorts(localBPorts); | 248 | string localBPortsStr = DescribePorts(localBPorts); |
| 256 | 249 | ||
| 257 | std::string description = "EdgeInfo{"; | 250 | std::string description = "EdgeInfo{"; |
| 258 | - description += StringFormat("netLayer=%u", netLayer); | ||
| 259 | description += StringFormat("topoType=%s", topoType.Describe().c_str()); | 251 | description += StringFormat("topoType=%s", topoType.Describe().c_str()); |
| 260 | description += StringFormat(", topoInstanceId=%u", topoInstId); | 252 | description += StringFormat(", topoInstanceId=%u", topoInstId); |
| 261 | description += StringFormat(", protocols=%s", protocolStr.str().c_str()); | 253 | description += StringFormat(", protocols=%s", protocolStr.str().c_str()); |
| @@ -285,7 +277,8 @@ std::string EdgeInfo::DescribePorts(std::set<std::string> ports) const | |||
| 285 | 277 | ||
| 286 | void EdgeInfo::GetBinStream(BinaryStream& binaryStream) const | 278 | void EdgeInfo::GetBinStream(BinaryStream& binaryStream) const |
| 287 | { | 279 | { |
| 288 | - binaryStream << netLayer << static_cast<u32>(linkType) << static_cast<u32>(topoType) << topoInstId; | 280 | + // 保留旧快照占位字段,不参与拓扑语义。 |
| 281 | + binaryStream << LEGACY_BINARY_LAYER << static_cast<u32>(linkType) << static_cast<u32>(topoType) << topoInstId; | ||
| 289 | binaryStream << protocols.size(); | 282 | binaryStream << protocols.size(); |
| 290 | for (LinkProtocol protocol : protocols) { | 283 | for (LinkProtocol protocol : protocols) { |
| 291 | binaryStream << static_cast<u32>(protocol); | 284 | binaryStream << static_cast<u32>(protocol); |
| @@ -308,7 +301,8 @@ void EdgeInfo::GetBinStream(BinaryStream& binaryStream) const | |||
| 308 | 301 | ||
| 309 | EdgeInfo::EdgeInfo(BinaryStream& binaryStream) | 302 | EdgeInfo::EdgeInfo(BinaryStream& binaryStream) |
| 310 | { | 303 | { |
| 311 | - binaryStream >> netLayer; | 304 | + u32 ignoredBinaryLayer; |
| 305 | + binaryStream >> ignoredBinaryLayer; | ||
| 312 | u32 linkTypeTmp; | 306 | u32 linkTypeTmp; |
| 313 | binaryStream >> linkTypeTmp; | 307 | binaryStream >> linkTypeTmp; |
| 314 | linkType = static_cast<LinkType::Value>(linkTypeTmp); | 308 | linkType = static_cast<LinkType::Value>(linkTypeTmp); |
| @@ -21,9 +21,9 @@ | |||
| 21 | 21 | ||
| 22 | namespace Hccl { | 22 | namespace Hccl { |
| 23 | 23 | ||
| 24 | -constexpr unsigned int MAX_VALUE_LEVEL = 7; | ||
| 25 | constexpr u32 PORT_MAX_LENGTH = 32; | 24 | constexpr u32 PORT_MAX_LENGTH = 32; |
| 26 | constexpr u32 MAX_PORTS_SIZE = 64; | 25 | constexpr u32 MAX_PORTS_SIZE = 64; |
| 26 | +constexpr u32 LEGACY_BINARY_LAYER = 0; | ||
| 27 | 27 | ||
| 28 | class EdgeInfo { | 28 | class EdgeInfo { |
| 29 | public: | 29 | public: |
| @@ -31,7 +31,6 @@ public: | |||
| 31 | EdgeInfo(BinaryStream& binaryStream); | 31 | EdgeInfo(BinaryStream& binaryStream); |
| 32 | ~EdgeInfo() {}; | 32 | ~EdgeInfo() {}; |
| 33 | 33 | ||
| 34 | - u32 netLayer{0}; | ||
| 35 | LinkType linkType; | 34 | LinkType linkType; |
| 36 | TopoType topoType{TopoType::CLOS}; | 35 | TopoType topoType{TopoType::CLOS}; |
| 37 | u32 topoInstId{0}; | 36 | u32 topoInstId{0}; |
| @@ -49,6 +49,20 @@ void TopoInfo::Deserialize(const nlohmann::json& topoInfoJson) | |||
| 49 | 49 | ||
| 50 | DeserializePeers(topoInfoJson); | 50 | DeserializePeers(topoInfoJson); |
| 51 | DeserializeEdges(topoInfoJson); | 51 | DeserializeEdges(topoInfoJson); |
| 52 | + | ||
| 53 | + u32 peer2PeerEdgeCount = 0; | ||
| 54 | + u32 peer2NetEdgeCount = 0; | ||
| 55 | + for (const auto& edge : edges) { | ||
| 56 | + if (edge.linkType == LinkType::PEER2PEER) { | ||
| 57 | + ++peer2PeerEdgeCount; | ||
| 58 | + } else if (edge.linkType == LinkType::PEER2NET) { | ||
| 59 | + ++peer2NetEdgeCount; | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + HCCL_DEBUG( | ||
| 64 | + "[TopoInfo::%s] deserialize summary: peers[%zu], edges[%zu], PEER2PEER[%u], PEER2NET[%u]", __func__, | ||
| 65 | + peers.size(), edges.size(), peer2PeerEdgeCount, peer2NetEdgeCount); | ||
| 52 | } | 66 | } |
| 53 | 67 | ||
| 54 | void TopoInfo::DeserializePeers(const nlohmann::json& topoInfoJson) | 68 | void TopoInfo::DeserializePeers(const nlohmann::json& topoInfoJson) |
| @@ -83,20 +97,17 @@ void TopoInfo::VerifyEdges(EdgeInfo& edge) | |||
| 83 | "[TopoInfo::%s] endpoint localId [%u] or [%u] is not exist in peers[%zu].", __func__, edge.localA, | 97 | "[TopoInfo::%s] endpoint localId [%u] or [%u] is not exist in peers[%zu].", __func__, edge.localA, |
| 84 | edge.localB, idSet.size())); | 98 | edge.localB, idSet.size())); |
| 85 | } | 99 | } |
| 86 | - // 检查edge.netLayer这一层级是否存在,不存在则初始化 | 100 | + // net_layer 不参与边语义;线性查重合并旧 topo 重复边,复杂度 O(E²)。 |
| 87 | - if (edges.find(edge.netLayer) == edges.end()) { | 101 | + if (find(edges.begin(), edges.end(), edge) != edges.end()) { |
[LOW] VerifyEdges 线性查重 O(E²),大拓扑下性能退化 第 105 行 建议修复:
若未来拓扑边数可能达数百级,可引入 ![]() ![]() | |||
| 88 | - edges[edge.netLayer] = vector<EdgeInfo>(); | 102 | + HCCL_DEBUG( |
| 89 | - } | 103 | + "[TopoInfo::%s] ignore duplicate physical edge, linkType[%s], topoType[%s], " |
| 90 | - // 判断edge.netLayer该层级是否存在重复edge | 104 | + "topoInstanceId[%u], localA[%u], localB[%u].", |
| 91 | - if (find(edges[edge.netLayer].begin(), edges[edge.netLayer].end(), edge) != edges[edge.netLayer].end()) { | 105 | + __func__, edge.linkType.Describe().c_str(), edge.topoType.Describe().c_str(), edge.topoInstId, edge.localA, |
| 92 | - THROW<InvalidParamsException>(StringFormat( | 106 | + edge.localB); |
| 93 | - "[TopoInfo::%s] exist duplicate edges. Location information:{edge.netLayer=%u, edge.linkType=%s, " | 107 | + return; |
| 94 | - "edge.topoType=%s, edge.topoInstanceId=%u, localA=%u, localB=%u}", | ||
| 95 | - __func__, edge.netLayer, edge.linkType.Describe().c_str(), edge.topoType.Describe().c_str(), | ||
| 96 | - edge.topoInstId, edge.localA, edge.localB)); | ||
| 97 | } | 108 | } |
🟡 Medium Priority changed line: affected behavior/contract:旧 topo.json 在同一 netLayer 内出现重复边会被立即检测并报错退出;新代码对任意重复边(跨层或同层)均静默忽略,不再报错。 failure mode:如果 topo.json 因生成工具 BUG 或人工编辑错误包含了不应存在的重复边(例如端口集合不同但其他字段相同的"假重复"),这些边会被静默丢弃,导致物理拓扑图中缺失合法边,进而可能造成 RankGraph 构建不完整、集合通信链路缺失或性能下降,且排查困难。 suggested fix:保留重复边合并的语义,但应当通过 建议:将 HCCL_DEBUG 提升为 HCCL_WARNING 或 HCCL_INFO,确保运维可感知边被合并。可考虑在 DeserializeEdges 末尾汇总合并数量并记录 WARNING。 ![]() ![]() 不准确? | |||
| 98 | 109 | ||
| 99 | - edges[edge.netLayer].emplace_back(edge); | 110 | + edges.emplace_back(edge); |
| 100 | } | 111 | } |
| 101 | 112 | ||
| 102 | void TopoInfo::DeserializeEdges(const nlohmann::json& topoInfoJson) | 113 | void TopoInfo::DeserializeEdges(const nlohmann::json& topoInfoJson) |
| @@ -114,21 +125,19 @@ void TopoInfo::DeserializeEdges(const nlohmann::json& topoInfoJson) | |||
| 114 | return; | 125 | return; |
| 115 | } | 126 | } |
| 116 | } | 127 | } |
| 128 | + if (edgeJsons.size() != edgeCount) { | ||
| 129 | + THROW<InvalidParamsException>(StringFormat( | ||
| 130 | + "[TopoInfo::%s] Value of edge_count[%u] is inconsistent with the size of edge_list[%zu].", __func__, | ||
| 131 | + edgeCount, edgeJsons.size())); | ||
| 132 | + } | ||
| 117 | for (auto& edgeJson : edgeJsons) { | 133 | for (auto& edgeJson : edgeJsons) { |
| 118 | EdgeInfo edge; | 134 | EdgeInfo edge; |
| 119 | edge.Deserialize(edgeJson); | 135 | edge.Deserialize(edgeJson); |
| 120 | VerifyEdges(edge); | 136 | VerifyEdges(edge); |
| 121 | } | 137 | } |
| 122 | 138 | ||
| 123 | - size_t sumEdge = 0; | 139 | + // edgeCount 对外表示去重后的物理边数量。 |
| 124 | - for (const auto& entry : edges) { | 140 | + edgeCount = static_cast<u32>(edges.size()); |
| 125 | - sumEdge += entry.second.size(); | ||
| 126 | - } | ||
| 127 | - if (sumEdge != edgeCount) { | ||
| 128 | - THROW<InvalidParamsException>(StringFormat( | ||
| 129 | - "[TopoInfo::%s] Value of edge_count[%u] is inconsistent with the size of edge_list[%zu].", __func__, | ||
| 130 | - edgeCount, sumEdge)); | ||
| 131 | - } | ||
| 132 | } | 141 | } |
| 133 | 142 | ||
| 134 | string TopoInfo::Describe() const | 143 | string TopoInfo::Describe() const |
| @@ -152,11 +161,8 @@ void TopoInfo::Dump() const | |||
| 152 | HCCL_DEBUG("%s", peer.Describe().c_str()); | 161 | HCCL_DEBUG("%s", peer.Describe().c_str()); |
| 153 | } | 162 | } |
| 154 | HCCL_DEBUG("edges:"); | 163 | HCCL_DEBUG("edges:"); |
| 155 | - for (const auto& itor : edges) { | 164 | + for (const auto& edge : edges) { |
| 156 | - HCCL_DEBUG("netLayer[%u]:", itor.first); | 165 | + HCCL_DEBUG(" %s", edge.Describe().c_str()); |
| 157 | - for (const auto& edge : itor.second) { | ||
| 158 | - HCCL_DEBUG(" %s", edge.Describe().c_str()); | ||
| 159 | - } | ||
| 160 | } | 166 | } |
| 161 | } | 167 | } |
| 162 | 168 | ||
| @@ -169,23 +175,27 @@ TopoInfo::TopoInfo(BinaryStream& binaryStream) | |||
| 169 | PeerInfo peer(binaryStream); | 175 | PeerInfo peer(binaryStream); |
| 170 | peers.emplace_back(peer); | 176 | peers.emplace_back(peer); |
| 171 | } | 177 | } |
| 172 | - size_t edgesSize = 0; | 178 | + size_t edgeGroupCount = 0; |
| 173 | - binaryStream >> edgesSize; | 179 | + binaryStream >> edgeGroupCount; |
| 174 | 180 | ||
| 175 | HCCL_INFO( | 181 | HCCL_INFO( |
| 176 | - "[TopoInfo] version is [%s], peerCount is [%u], edgeCount is [%u], peers size is [%u], edges size is [%u]", | 182 | + "[TopoInfo] version is [%s], peerCount is [%u], edgeCount is [%u], peers size is [%zu], " |
| 177 | - version.c_str(), peerCount, edgeCount, peers.size(), edgesSize); | 183 | + "edge group count is [%zu]", |
| 178 | - for (u32 i = 0; i < edgesSize; i++) { | 184 | + version.c_str(), peerCount, edgeCount, peers.size(), edgeGroupCount); |
| 179 | - u32 edgeInfoIndex = 0; | 185 | + // 保留旧快照分组外壳,读取后统一展开物理边。 |
| 180 | - binaryStream >> edgeInfoIndex; // key | 186 | + for (size_t i = 0; i < edgeGroupCount; i++) { |
| 181 | - size_t edgeSize = 0; | 187 | + u32 ignoredBinaryLayer = 0; |
| 182 | - binaryStream >> edgeSize; | 188 | + size_t groupEdgeCount = 0; |
| 183 | - HCCL_INFO("[TopoInfo] edges key is [%u], value size is [%u]", edgeInfoIndex, edgeSize); | 189 | + binaryStream >> ignoredBinaryLayer >> groupEdgeCount; |
| 184 | - for (u32 j = 0; j < edgeSize; j++) { // value | 190 | + for (size_t j = 0; j < groupEdgeCount; j++) { |
| 185 | EdgeInfo edge(binaryStream); | 191 | EdgeInfo edge(binaryStream); |
| 186 | - edges[edgeInfoIndex].emplace_back(edge); | 192 | + // 旧快照可能按 layer 重复存储同一物理边,展开时合并。 |
| 193 | + if (find(edges.begin(), edges.end(), edge) == edges.end()) { | ||
| 194 | + edges.emplace_back(edge); | ||
| 195 | + } | ||
| 187 | } | 196 | } |
| 188 | } | 197 | } |
| 198 | + edgeCount = static_cast<u32>(edges.size()); | ||
| 189 | } | 199 | } |
| 190 | 200 | ||
| 191 | void TopoInfo::GetBinStream(BinaryStream& binaryStream) const | 201 | void TopoInfo::GetBinStream(BinaryStream& binaryStream) const |
| @@ -195,16 +205,16 @@ void TopoInfo::GetBinStream(BinaryStream& binaryStream) const | |||
| 195 | for (auto& it : peers) { | 205 | for (auto& it : peers) { |
| 196 | it.GetBinStream(binaryStream); | 206 | it.GetBinStream(binaryStream); |
| 197 | } | 207 | } |
| 198 | - binaryStream << edges.size(); | 208 | + const size_t edgeGroupCount = edges.empty() ? 0 : 1; |
| 209 | + binaryStream << edgeGroupCount; | ||
| 199 | HCCL_INFO( | 210 | HCCL_INFO( |
| 200 | - "[TopoInfo::GetBinStream] version is [%s], peerCount is [%u], edgeCount is [%u], peers size is [%u], edges " | 211 | + "[TopoInfo::GetBinStream] version is [%s], peerCount is [%u], edgeCount is [%u], peers size is [%zu], " |
| 201 | - "size is [%u]", | 212 | + "edges size is [%zu]", |
| 202 | version.c_str(), peerCount, edgeCount, peers.size(), edges.size()); | 213 | version.c_str(), peerCount, edgeCount, peers.size(), edges.size()); |
| 203 | - for (auto& it : edges) { | 214 | + // 新快照统一写入一个兼容分组,不恢复逻辑分层。 |
| 204 | - binaryStream << it.first; | 215 | + if (!edges.empty()) { |
| 205 | - binaryStream << it.second.size(); | 216 | + binaryStream << LEGACY_BINARY_LAYER << edges.size(); |
| 206 | - HCCL_INFO("[TopoInfo::GetBinStream] edges key is [%u], value size is [%u]", it.first, it.second.size()); | 217 | + for (const auto& edge : edges) { |
| 207 | - for (auto& edge : it.second) { | ||
| 208 | edge.GetBinStream(binaryStream); | 218 | edge.GetBinStream(binaryStream); |
| 209 | } | 219 | } |
| 210 | } | 220 | } |
| @@ -11,7 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | - | ||
| 15 | 14 | ||
| 16 | 15 | ||
| 17 | 16 | ||
| @@ -28,7 +27,7 @@ public: | |||
| 28 | u32 peerCount{0}; | 27 | u32 peerCount{0}; |
| 29 | u32 edgeCount{0}; | 28 | u32 edgeCount{0}; |
| 30 | std::vector<PeerInfo> peers; | 29 | std::vector<PeerInfo> peers; |
| 31 | - std::map<u32, std::vector<EdgeInfo>> edges; | 30 | + std::vector<EdgeInfo> edges; |
| 32 | void Deserialize(const nlohmann::json& topoInfoJson); | 31 | void Deserialize(const nlohmann::json& topoInfoJson); |
| 33 | std::string Describe() const; | 32 | std::string Describe() const; |
| 34 | void Dump() const; | 33 | void Dump() const; |
| @@ -8,6 +8,7 @@ | |||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | 8 | * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | + | ||
| 11 | 12 | ||
| 12 | 13 | ||
| 13 | 14 | ||
| @@ -145,6 +146,25 @@ namespace { | |||
| 145 | CheckTopoFilePath(topoFilePath); | 146 | CheckTopoFilePath(topoFilePath); |
| 146 | return topoFilePath; | 147 | return topoFilePath; |
| 147 | } | 148 | } |
| 149 | + | ||
| 150 | + bool IsHostRdmaLink(const std::shared_ptr<PhyTopo::Link>& link) | ||
| 151 | + { | ||
| 152 | + if (link == nullptr || link->GetSourceIFace() == nullptr | ||
| 153 | + || link->GetSourceIFace()->GetPos() != AddrPosition::HOST) { | ||
| 154 | + return false; | ||
| 155 | + } | ||
| 156 | + const std::set<LinkProtocol>& protocols = link->GetLinkProtocols(); | ||
| 157 | + return std::any_of(protocols.begin(), protocols.end(), [](const LinkProtocol& protocol) { | ||
| 158 | + return LinkProtocol2LinkProtoType(protocol) == LinkProtoType::RDMA; | ||
| 159 | + }); | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + bool HasMatchingPort(const AddressInfo& addrInfo, const std::set<std::string>& phyPorts) | ||
| 163 | + { | ||
| 164 | + return std::any_of(addrInfo.ports.begin(), addrInfo.ports.end(), [&phyPorts](const std::string& port) { | ||
| 165 | + return phyPorts.count(port) != 0; | ||
| 166 | + }); | ||
| 167 | + } | ||
| 148 | } // namespace | 168 | } // namespace |
| 149 | 169 | ||
| 150 | void RankInfoDetectClient::Setup(RankTableInfo& rankTable) | 170 | void RankInfoDetectClient::Setup(RankTableInfo& rankTable) |
| @@ -721,30 +741,33 @@ void RankInfoDetectClient::HostListenPortDetect(NewRankInfo& rankInfo) | |||
| 721 | auto devLogicId = HrtGetDevice(); | 741 | auto devLogicId = HrtGetDevice(); |
| 722 | u32 devPhyId = rankInfo.deviceId; | 742 | u32 devPhyId = rankInfo.deviceId; |
| 723 | for (auto& rankLevelInfo : rankInfo.rankLevelInfos) { | 743 | for (auto& rankLevelInfo : rankInfo.rankLevelInfos) { |
| 724 | - shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> graph | 744 | + // 物理图不区分逻辑层,按 RankTable 端口匹配当前层。 |
| 725 | - = PhyTopo::GetInstance()->GetTopoGraph(rankLevelInfo.netLayer); | 745 | + auto graph = PhyTopo::GetInstance()->GetTopoGraph(); |
| 726 | if (graph == nullptr) { | 746 | if (graph == nullptr) { |
| 727 | - HCCL_DEBUG("[RankInfoDetectClient::%s]Can't find the layout %u Graph!", __func__, rankLevelInfo.netLayer); | 747 | + HCCL_DEBUG("[RankInfoDetectClient::%s] Physical topo graph is nullptr.", __func__); |
| 728 | continue; | 748 | continue; |
| 729 | } | 749 | } |
| 730 | std::vector<std::shared_ptr<PhyTopo::Link>> links = graph->GetEdges(rankInfo.localId); | 750 | std::vector<std::shared_ptr<PhyTopo::Link>> links = graph->GetEdges(rankInfo.localId); |
| 731 | for (auto& link : links) { | 751 | for (auto& link : links) { |
| 732 | - if (link->GetSourceIFace()->GetPos() != AddrPosition::HOST) { | 752 | + if (!IsHostRdmaLink(link)) { |
| 733 | continue; | 753 | continue; |
| 734 | } | 754 | } |
| 735 | - const std::set<LinkProtocol>& protocols = link->GetLinkProtocols(); | 755 | + const auto& phyPorts = link->GetSourceIFace()->GetPorts(); |
| 736 | - for (auto& protocol : protocols) { | 756 | + // 使用物理 Host RDMA 端口对应的地址,不默认取首个地址。 |
| 737 | - LinkProtoType protoType = LinkProtocol2LinkProtoType(protocol); | 757 | + auto addrIt = std::find_if( |
| 738 | - if (protoType != LinkProtoType::RDMA || rankLevelInfo.rankAddrs.empty()) { | 758 | + rankLevelInfo.rankAddrs.begin(), rankLevelInfo.rankAddrs.end(), |
| 739 | - continue; | 759 | + [&phyPorts](const AddressInfo& addrInfo) { |
| 740 | - } | 760 | + return HasMatchingPort(addrInfo, phyPorts); |
| 741 | - HCCL_DEBUG("[SocketManager::%s] find the host rdma link %s", __func__, link->Describe().c_str()); | 761 | + }); |
| 742 | - const IpAddress& hostIp = rankLevelInfo.rankAddrs[0].addr; | 762 | + if (addrIt == rankLevelInfo.rankAddrs.end()) { |
| 743 | - uint32_t hostPort = 0; | 763 | + continue; |
| 744 | - SetupHostListenPort(devLogicId, devPhyId, hostIp, hostPort); | ||
| 745 | - rankInfo.hostPort = hostPort; | ||
| 746 | - return; | ||
| 747 | } | 764 | } |
| 765 | + HCCL_DEBUG("[SocketManager::%s] find the host rdma link %s", __func__, link->Describe().c_str()); | ||
| 766 | + const IpAddress& hostIp = addrIt->addr; | ||
| 767 | + uint32_t hostPort = 0; | ||
| 768 | + SetupHostListenPort(devLogicId, devPhyId, hostIp, hostPort); | ||
| 769 | + rankInfo.hostPort = hostPort; | ||
| 770 | + return; | ||
| 748 | } | 771 | } |
| 749 | } | 772 | } |
| 750 | } | 773 | } |
| @@ -3820,7 +3820,7 @@ HcclResult CommunicatorImpl::GetInstSizeListByNetLayer(uint32_t netLayer, uint32 | |||
| 3820 | } | 3820 | } |
| 3821 | } | 3821 | } |
| 3822 | 3822 | ||
| 3823 | -static HcclResult InsertInnerLink(const NetInstance::Path& path, std::vector<CommLink>& linkListVec) | 3823 | +static HcclResult InsertInnerLink(u32 netLayer, const NetInstance::Path& path, std::vector<CommLink>& linkListVec) |
| 3824 | { | 3824 | { |
| 3825 | for (const auto& link : path.links) { | 3825 | for (const auto& link : path.links) { |
| 3826 | const NetInstance::Link* peer2peer = &link; | 3826 | const NetInstance::Link* peer2peer = &link; |
| @@ -3839,6 +3839,7 @@ static HcclResult InsertInnerLink(const NetInstance::Path& path, std::vector<Com | |||
| 3839 | HcclResult result = GetCommAddr(commLink.srcEndpointDesc.commAddr, srcConnInterface->GetAddr()); | 3839 | HcclResult result = GetCommAddr(commLink.srcEndpointDesc.commAddr, srcConnInterface->GetAddr()); |
| 3840 | if (result != HCCL_SUCCESS) | 3840 | if (result != HCCL_SUCCESS) |
| 3841 | return result; | 3841 | return result; |
| 3842 | + CHK_RET(SetEndpointTopoInfo(commLink.srcEndpointDesc, netLayer, srcConnInterface->GetTopoInstId())); | ||
| 3842 | 3843 | ||
| 3843 | // 设置目标端点 | 3844 | // 设置目标端点 |
| 3844 | std::shared_ptr<NetInstance::ConnInterface> dstConnInterface = link.GetTargetIface(); | 3845 | std::shared_ptr<NetInstance::ConnInterface> dstConnInterface = link.GetTargetIface(); |
| @@ -3846,6 +3847,7 @@ static HcclResult InsertInnerLink(const NetInstance::Path& path, std::vector<Com | |||
| 3846 | result = GetCommAddr(commLink.dstEndpointDesc.commAddr, dstConnInterface->GetAddr()); | 3847 | result = GetCommAddr(commLink.dstEndpointDesc.commAddr, dstConnInterface->GetAddr()); |
| 3847 | if (result != HCCL_SUCCESS) | 3848 | if (result != HCCL_SUCCESS) |
| 3848 | return result; | 3849 | return result; |
| 3850 | + CHK_RET(SetEndpointTopoInfo(commLink.dstEndpointDesc, netLayer, dstConnInterface->GetTopoInstId())); | ||
| 3849 | 3851 | ||
| 3850 | linkListVec.emplace_back(std::move(commLink)); | 3852 | linkListVec.emplace_back(std::move(commLink)); |
| 3851 | } | 3853 | } |
| @@ -3854,7 +3856,7 @@ static HcclResult InsertInnerLink(const NetInstance::Path& path, std::vector<Com | |||
| 3854 | return HCCL_SUCCESS; | 3856 | return HCCL_SUCCESS; |
| 3855 | } | 3857 | } |
| 3856 | 3858 | ||
| 3857 | -static HcclResult InsertClosLinks(const NetInstance::Path& path, std::vector<CommLink>& linkListVec) | 3859 | +static HcclResult InsertClosLinks(u32 netLayer, const NetInstance::Path& path, std::vector<CommLink>& linkListVec) |
| 3858 | { | 3860 | { |
| 3859 | const NetInstance::Link* peer2net = nullptr; | 3861 | const NetInstance::Link* peer2net = nullptr; |
| 3860 | const NetInstance::Link* net2peer = nullptr; | 3862 | const NetInstance::Link* net2peer = nullptr; |
| @@ -3886,10 +3888,12 @@ static HcclResult InsertClosLinks(const NetInstance::Path& path, std::vector<Com | |||
| 3886 | HcclResult result = GetCommAddr(commLink.srcEndpointDesc.commAddr, srcInterface->GetAddr()); | 3888 | HcclResult result = GetCommAddr(commLink.srcEndpointDesc.commAddr, srcInterface->GetAddr()); |
| 3887 | if (result != HCCL_SUCCESS) | 3889 | if (result != HCCL_SUCCESS) |
| 3888 | return result; | 3890 | return result; |
| 3891 | + CHK_RET(SetEndpointTopoInfo(commLink.srcEndpointDesc, netLayer, srcInterface->GetTopoInstId())); | ||
| 3889 | // 设置目标端点 | 3892 | // 设置目标端点 |
| 3890 | result = GetCommAddr(commLink.dstEndpointDesc.commAddr, dstInterface->GetAddr()); | 3893 | result = GetCommAddr(commLink.dstEndpointDesc.commAddr, dstInterface->GetAddr()); |
| 3891 | if (result != HCCL_SUCCESS) | 3894 | if (result != HCCL_SUCCESS) |
| 3892 | return result; | 3895 | return result; |
| 3896 | + CHK_RET(SetEndpointTopoInfo(commLink.dstEndpointDesc, netLayer, dstInterface->GetTopoInstId())); | ||
| 3893 | linkListVec.emplace_back(std::move(commLink)); | 3897 | linkListVec.emplace_back(std::move(commLink)); |
| 3894 | } | 3898 | } |
| 3895 | return HCCL_SUCCESS; | 3899 | return HCCL_SUCCESS; |
| @@ -3915,12 +3919,12 @@ HcclResult CommunicatorImpl::GetLinks( | |||
| 3915 | } | 3919 | } |
| 3916 | if (!isClos) { | 3920 | if (!isClos) { |
| 3917 | // Peer2Peer网络:直接处理每条link | 3921 | // Peer2Peer网络:直接处理每条link |
| 3918 | - HcclResult ret = InsertInnerLink(path, linkListVec); | 3922 | + HcclResult ret = InsertInnerLink(netLayer, path, linkListVec); |
| 3919 | if (ret != HCCL_SUCCESS) | 3923 | if (ret != HCCL_SUCCESS) |
| 3920 | return ret; | 3924 | return ret; |
| 3921 | } else { | 3925 | } else { |
| 3922 | // Clos网络:找到peer2net和net2peer,组合成一条链路 | 3926 | // Clos网络:找到peer2net和net2peer,组合成一条链路 |
| 3923 | - HcclResult ret = InsertClosLinks(path, linkListVec); | 3927 | + HcclResult ret = InsertClosLinks(netLayer, path, linkListVec); |
| 3924 | if (ret != HCCL_SUCCESS) | 3928 | if (ret != HCCL_SUCCESS) |
| 3925 | return ret; | 3929 | return ret; |
| 3926 | } | 3930 | } |
| @@ -258,10 +258,10 @@ void SocketManager::ServerInitAll(NewRankInfo& rankInfo) | |||
| 258 | u32 localId = rankInfo.localId; | 258 | u32 localId = rankInfo.localId; |
| 259 | u32 devicePhyId = rankInfo.deviceId; | 259 | u32 devicePhyId = rankInfo.deviceId; |
| 260 | for (auto& rankLevelInfo : rankInfo.rankLevelInfos) { | 260 | for (auto& rankLevelInfo : rankInfo.rankLevelInfos) { |
| 261 | - shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> graph | 261 | + // 物理图不区分逻辑层,按 RankTable 端口筛选当前层链路。 |
| 262 | - = PhyTopo::GetInstance()->GetTopoGraph(rankLevelInfo.netLayer); | 262 | + auto graph = PhyTopo::GetInstance()->GetTopoGraph(); |
| 263 | if (graph == nullptr) { | 263 | if (graph == nullptr) { |
| 264 | - HCCL_DEBUG("[SocketManager::%s]Can't find the layout %u Graph!", __func__, rankLevelInfo.netLayer); | 264 | + HCCL_DEBUG("[SocketManager::%s] Physical topo graph is nullptr.", __func__); |
| 265 | continue; | 265 | continue; |
| 266 | } | 266 | } |
| 267 | std::vector<std::shared_ptr<PhyTopo::Link>> links = graph->GetEdges(localId); | 267 | std::vector<std::shared_ptr<PhyTopo::Link>> links = graph->GetEdges(localId); |
| @@ -276,7 +276,7 @@ void SocketManager::ServerInitAll(NewRankInfo& rankInfo) | |||
| 276 | LinkProtoType protoType = LinkProtocol2LinkProtoType(protocol); | 276 | LinkProtoType protoType = LinkProtocol2LinkProtoType(protocol); |
| 277 | const std::set<std::string>& ports = link->GetSourceIFace()->GetPorts(); | 277 | const std::set<std::string>& ports = link->GetSourceIFace()->GetPorts(); |
| 278 | for (auto& rankAddr : rankLevelInfo.rankAddrs) { | 278 | for (auto& rankAddr : rankLevelInfo.rankAddrs) { |
| 279 | - // topo查得网口使用则打开建链 | 279 | + // 仅为当前 RankTable 层命中的物理端口创建监听。 |
| 280 | std::set<std::string> intersectSet; | 280 | std::set<std::string> intersectSet; |
| 281 | std::set_intersection( | 281 | std::set_intersection( |
| 282 | ports.begin(), ports.end(), rankAddr.ports.begin(), rankAddr.ports.end(), | 282 | ports.begin(), ports.end(), rankAddr.ports.begin(), rankAddr.ports.end(), |
| @@ -13,7 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | - | ||
| 17 | 16 | ||
| 18 | 17 | ||
| 19 | 18 | ||
| @@ -116,16 +115,15 @@ public: | |||
| 116 | u32 hop{1}; | 115 | u32 hop{1}; |
| 117 | }; | 116 | }; |
| 118 | 117 | ||
| 119 | - void AddTopoGraph(const u32 netLayer, std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo); | 118 | + void AddTopoGraph(std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo); |
| 120 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> GetTopoGraph(const u32 netLayer) const; | 119 | + std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> GetTopoGraph() const; |
| 121 | void InitFinish(); | 120 | void InitFinish(); |
| 122 | bool IsInitFinished() const; | 121 | bool IsInitFinished() const; |
| 123 | void Clear(); | 122 | void Clear(); |
| 124 | void Dump() const; | 123 | void Dump() const; |
| 125 | - bool IsNetLayerExisted(const u32 netLayer) const; | ||
| 126 | 124 | ||
| 127 | private: | 125 | private: |
| 128 | - std::unordered_map<u32, std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>>> topos; | 126 | + std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo_{nullptr}; |
| 129 | bool initFlag{false}; | 127 | bool initFlag{false}; |
| 130 | }; | 128 | }; |
| 131 | } // namespace Hccl | 129 | } // namespace Hccl |
| @@ -44,6 +44,7 @@ public: | |||
| 44 | private: | 44 | private: |
| 45 | std::shared_ptr<TopoInfo> LoadTopoInfo(const std::string& topoPath); | 45 | std::shared_ptr<TopoInfo> LoadTopoInfo(const std::string& topoPath); |
| 46 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> CreateGraph(const std::vector<EdgeInfo>& edges) const; | 46 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> CreateGraph(const std::vector<EdgeInfo>& edges) const; |
| 47 | + void BuildPhyTopo(const TopoInfo& topoInfo) const; | ||
| 47 | std::shared_ptr<TopoInfo> topoInfo_; | 48 | std::shared_ptr<TopoInfo> topoInfo_; |
| 48 | std::mutex phyTopoMutex; | 49 | std::mutex phyTopoMutex; |
| 49 | }; | 50 | }; |
| @@ -23,10 +23,72 @@ | |||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | + | ||
| 26 | 27 | ||
| 27 | 28 | ||
| 28 | namespace Hccl { | 29 | namespace Hccl { |
| 29 | constexpr u32 DEFAULT_LISTENING_PORT = 60001; | 30 | constexpr u32 DEFAULT_LISTENING_PORT = 60001; |
| 31 | +// HCCL构建ChannelDesc时会完整复制EndpointLoc,使用其未占用的尾部字节传递拓扑定位信息。 | ||
| 32 | +struct EndpointTopoInfo { | ||
| 33 | + u32 magic; | ||
| 34 | + u32 netLayer; | ||
| 35 | + u32 topoInstId; | ||
| 36 | +}; | ||
| 37 | + | ||
| 38 | +constexpr u32 ENDPOINT_TOPO_INFO_MAGIC = 0x544F504FU; | ||
| 39 | +constexpr size_t ENDPOINT_LOC_RAW_SIZE = sizeof(((EndpointLoc*)nullptr)->raws); | ||
| 40 | +static_assert(ENDPOINT_LOC_RAW_SIZE >= sizeof(EndpointTopoInfo), "EndpointLoc reserved space is insufficient"); | ||
| 41 | +static_assert( | ||
| 42 | + ENDPOINT_LOC_RAW_SIZE - sizeof(EndpointTopoInfo) >= sizeof(((EndpointLoc*)nullptr)->device), | ||
| 43 | + "Endpoint topology info overlaps device location fields"); | ||
| 44 | +constexpr size_t ENDPOINT_TOPO_INFO_OFFSET = ENDPOINT_LOC_RAW_SIZE - sizeof(EndpointTopoInfo); | ||
| 45 | + | ||
| 46 | +inline HcclResult SetEndpointTopoInfo(EndpointDesc& endpointDesc, u32 netLayer, u32 topoInstId) | ||
| 47 | +{ | ||
| 48 | + const EndpointTopoInfo topoInfo{ENDPOINT_TOPO_INFO_MAGIC, netLayer, topoInstId}; | ||
| 49 | + const errno_t ret | ||
| 50 | + = memcpy_s(endpointDesc.loc.raws + ENDPOINT_TOPO_INFO_OFFSET, sizeof(topoInfo), &topoInfo, sizeof(topoInfo)); | ||
| 51 | + return ret == EOK ? HCCL_SUCCESS : HCCL_E_MEMORY; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +inline bool GetEndpointTopoInfo(const EndpointDesc& endpointDesc, u32& netLayer, u32& topoInstId) | ||
| 55 | +{ | ||
| 56 | + EndpointTopoInfo topoInfo{}; | ||
| 57 | + const errno_t ret | ||
| 58 | + = memcpy_s(&topoInfo, sizeof(topoInfo), endpointDesc.loc.raws + ENDPOINT_TOPO_INFO_OFFSET, sizeof(topoInfo)); | ||
| 59 | + if (ret != EOK) { | ||
| 60 | + return false; | ||
| 61 | + } | ||
| 62 | + if (topoInfo.magic != ENDPOINT_TOPO_INFO_MAGIC) { | ||
| 63 | + return false; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + netLayer = topoInfo.netLayer; | ||
| 67 | + topoInstId = topoInfo.topoInstId; | ||
| 68 | + return true; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +// 同一地址和协议可属于不同网络层或拓扑实例,需共同参与Endpoint定位。 | ||
| 72 | +struct EndpointKey { | ||
| 73 | + u32 netLayer; | ||
| 74 | + u32 topoInstId; | ||
| 75 | + CommAddr commAddr; | ||
| 76 | + CommProtocol protocol; | ||
| 77 | + | ||
| 78 | + bool operator==(const EndpointKey& other) const | ||
| 79 | + { | ||
| 80 | + return netLayer == other.netLayer && topoInstId == other.topoInstId && commAddr == other.commAddr | ||
| 81 | + && protocol == other.protocol; | ||
| 82 | + } | ||
| 83 | +}; | ||
| 84 | + | ||
| 85 | +struct EndpointKeyHash { | ||
| 86 | + size_t operator()(const EndpointKey& key) const | ||
| 87 | + { | ||
| 88 | + return std::hash<u32>()(key.netLayer) ^ (std::hash<u32>()(key.topoInstId) << 1) | ||
| 89 | + ^ (std::hash<CommAddr>()(key.commAddr) << 2) ^ (std::hash<CommProtocol>()(key.protocol) << 3); | ||
| 90 | + } | ||
| 91 | +}; | ||
| 30 | class NetInstance { | 92 | class NetInstance { |
| 31 | public: | 93 | public: |
| 32 | class ConnInterface { | 94 | class ConnInterface { |
| @@ -70,6 +132,9 @@ public: | |||
| 70 | 132 | ||
| 71 | class Node { | 133 | class Node { |
| 72 | public: | 134 | public: |
| 135 | + using EndpointToIfaceMap | ||
| 136 | + = std::unordered_map<EndpointKey, std::shared_ptr<NetInstance::ConnInterface>, EndpointKeyHash>; | ||
| 137 | + | ||
| 73 | MAKE_ENUM(NodeType, PEER, FABRIC) | 138 | MAKE_ENUM(NodeType, PEER, FABRIC) |
| 74 | explicit Node(NodeType nodeType) : type_(nodeType) {} | 139 | explicit Node(NodeType nodeType) : type_(nodeType) {} |
| 75 | virtual ~Node() = default; | 140 | virtual ~Node() = default; |
| @@ -80,9 +145,9 @@ public: | |||
| 80 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfacesByLayer(u32 layer) const; | 145 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfacesByLayer(u32 layer) const; |
| 81 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfaces() const; | 146 | std::vector<std::shared_ptr<NetInstance::ConnInterface>> GetIfaces() const; |
| 82 | void SetEndpointToIface( | 147 | void SetEndpointToIface( |
| 83 | - const CommAddr& commAddr, CommProtocol protocol, const std::shared_ptr<NetInstance::ConnInterface>& iface); | 148 | + u32 netLayer, u32 topoInstId, const CommAddr& commAddr, CommProtocol protocol, |
| 84 | - const std::unordered_map<std::pair<CommAddr, CommProtocol>, std::shared_ptr<NetInstance::ConnInterface>> | 149 | + const std::shared_ptr<NetInstance::ConnInterface>& iface); |
| 85 | - GetEndpointToIfaceMap() const; | 150 | + const EndpointToIfaceMap& GetEndpointToIfaceMap() const; |
| 86 | NodeId GetNodeId() const; | 151 | NodeId GetNodeId() const; |
| 87 | string GetNodeIdStr() const; | 152 | string GetNodeIdStr() const; |
| 88 | const std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> | 153 | const std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> |
| @@ -94,8 +159,7 @@ public: | |||
| 94 | 159 | ||
| 95 | private: | 160 | private: |
| 96 | std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> interfacesMap_; | 161 | std::unordered_map<u32, std::vector<std::shared_ptr<NetInstance::ConnInterface>>> interfacesMap_; |
| 97 | - std::unordered_map<std::pair<CommAddr, CommProtocol>, std::shared_ptr<NetInstance::ConnInterface>> | 162 | + EndpointToIfaceMap endpointToIfaceMap_; |
| 98 | - endpointToIfaceMap_; | ||
| 99 | NodeType type_; | 163 | NodeType type_; |
| 100 | }; | 164 | }; |
| 101 | 165 | ||
| @@ -126,6 +190,7 @@ public: | |||
| 126 | std::set<u32> GetLevels() const; | 190 | std::set<u32> GetLevels() const; |
| 127 | NetInstancePtr GetNetInstance(u32 level) const; | 191 | NetInstancePtr GetNetInstance(u32 level) const; |
| 128 | std::map<std::string, std::vector<IpAddress>> GetPortAddrMapLayer0() const; | 192 | std::map<std::string, std::vector<IpAddress>> GetPortAddrMapLayer0() const; |
| 193 | + bool TryGetLayer0Address(const std::string& port, IpAddress& addr) const; | ||
| 129 | void SetPortPortAddrMapLayer0(std::map<std::string, std::vector<IpAddress>> portAddrMap); | 194 | void SetPortPortAddrMapLayer0(std::map<std::string, std::vector<IpAddress>> portAddrMap); |
| 130 | std::string Describe() const override; | 195 | std::string Describe() const override; |
| 131 | 196 | ||
| @@ -21,9 +21,9 @@ | |||
| 21 | 21 | ||
| 22 | namespace Hccl { | 22 | namespace Hccl { |
| 23 | 23 | ||
| 24 | -constexpr unsigned int MAX_VALUE_LEVEL = 7; | ||
| 25 | constexpr u32 PORT_MAX_LENGTH = 32; | 24 | constexpr u32 PORT_MAX_LENGTH = 32; |
| 26 | constexpr u32 MAX_PORTS_SIZE = 64; | 25 | constexpr u32 MAX_PORTS_SIZE = 64; |
| 26 | +constexpr u32 LEGACY_BINARY_LAYER = 0; | ||
| 27 | 27 | ||
| 28 | class EdgeInfo { | 28 | class EdgeInfo { |
| 29 | public: | 29 | public: |
| @@ -31,7 +31,6 @@ public: | |||
| 31 | EdgeInfo(BinaryStream& binaryStream); | 31 | EdgeInfo(BinaryStream& binaryStream); |
| 32 | ~EdgeInfo() {}; | 32 | ~EdgeInfo() {}; |
| 33 | 33 | ||
| 34 | - u32 netLayer{0}; | ||
| 35 | LinkType linkType; | 34 | LinkType linkType; |
| 36 | TopoType topoType{TopoType::CLOS}; | 35 | TopoType topoType{TopoType::CLOS}; |
| 37 | u32 topoInstId{0}; | 36 | u32 topoInstId{0}; |
| @@ -11,7 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | - | ||
| 15 | 14 | ||
| 16 | 15 | ||
| 17 | 16 | ||
| @@ -28,7 +27,7 @@ public: | |||
| 28 | u32 peerCount{0}; | 27 | u32 peerCount{0}; |
| 29 | u32 edgeCount{0}; | 28 | u32 edgeCount{0}; |
| 30 | std::vector<PeerInfo> peers; | 29 | std::vector<PeerInfo> peers; |
| 31 | - std::map<u32, std::vector<EdgeInfo>> edges; | 30 | + std::vector<EdgeInfo> edges; |
| 32 | void Deserialize(const nlohmann::json& topoInfoJson); | 31 | void Deserialize(const nlohmann::json& topoInfoJson); |
| 33 | std::string Describe() const; | 32 | std::string Describe() const; |
| 34 | void Dump() const; | 33 | void Dump() const; |
| @@ -210,7 +210,7 @@ static HcclResult SetEndpointLoc(EndpointLocType& locType, const AddrPosition& p | |||
| 210 | return HCCL_SUCCESS; | 210 | return HCCL_SUCCESS; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | -static HcclResult InsertInnerLink(const NetInstance::Path& path, std::vector<CommLink>& linkListVec) | 213 | +static HcclResult InsertInnerLink(u32 netLayer, const NetInstance::Path& path, std::vector<CommLink>& linkListVec) |
| 214 | { | 214 | { |
| 215 | for (const auto& link : path.links) { | 215 | for (const auto& link : path.links) { |
| 216 | const NetInstance::Link* peer2peer = &link; | 216 | const NetInstance::Link* peer2peer = &link; |
| @@ -234,6 +234,7 @@ static HcclResult InsertInnerLink(const NetInstance::Path& path, std::vector<Com | |||
| 234 | return result; | 234 | return result; |
| 235 | } | 235 | } |
| 236 | CHK_RET(SetEndpointLoc(commLink.srcEndpointDesc.loc.locType, srcConnInterface->GetPos())); | 236 | CHK_RET(SetEndpointLoc(commLink.srcEndpointDesc.loc.locType, srcConnInterface->GetPos())); |
| 237 | + CHK_RET(SetEndpointTopoInfo(commLink.srcEndpointDesc, netLayer, srcConnInterface->GetTopoInstId())); | ||
| 237 | 238 | ||
| 238 | // 设置目标端点 | 239 | // 设置目标端点 |
| 239 | std::shared_ptr<NetInstance::ConnInterface> dstConnInterface = link.GetTargetIface(); | 240 | std::shared_ptr<NetInstance::ConnInterface> dstConnInterface = link.GetTargetIface(); |
| @@ -247,6 +248,7 @@ static HcclResult InsertInnerLink(const NetInstance::Path& path, std::vector<Com | |||
| 247 | } | 248 | } |
| 248 | 249 | ||
| 249 | CHK_RET(SetEndpointLoc(commLink.dstEndpointDesc.loc.locType, dstConnInterface->GetPos())); | 250 | CHK_RET(SetEndpointLoc(commLink.dstEndpointDesc.loc.locType, dstConnInterface->GetPos())); |
| 251 | + CHK_RET(SetEndpointTopoInfo(commLink.dstEndpointDesc, netLayer, dstConnInterface->GetTopoInstId())); | ||
| 250 | 252 | ||
| 251 | if (commLink.srcEndpointDesc.loc.locType == ENDPOINT_LOC_TYPE_DEVICE) { | 253 | if (commLink.srcEndpointDesc.loc.locType == ENDPOINT_LOC_TYPE_DEVICE) { |
| 252 | std::shared_ptr<NetInstance::Node> srcNode = peer2peer->GetSourceNode(); | 254 | std::shared_ptr<NetInstance::Node> srcNode = peer2peer->GetSourceNode(); |
| @@ -264,7 +266,7 @@ static HcclResult InsertInnerLink(const NetInstance::Path& path, std::vector<Com | |||
| 264 | return HCCL_SUCCESS; | 266 | return HCCL_SUCCESS; |
| 265 | } | 267 | } |
| 266 | 268 | ||
| 267 | -static HcclResult InsertClosLinks(const NetInstance::Path& path, std::vector<CommLink>& linkListVec) | 269 | +static HcclResult InsertClosLinks(u32 netLayer, const NetInstance::Path& path, std::vector<CommLink>& linkListVec) |
| 268 | { | 270 | { |
| 269 | const NetInstance::Link* peer2net = nullptr; | 271 | const NetInstance::Link* peer2net = nullptr; |
| 270 | const NetInstance::Link* net2peer = nullptr; | 272 | const NetInstance::Link* net2peer = nullptr; |
| @@ -297,6 +299,7 @@ static HcclResult InsertClosLinks(const NetInstance::Path& path, std::vector<Com | |||
| 297 | // 设置源端点 | 299 | // 设置源端点 |
| 298 | CHK_RET(SetCommAddress(commLink.srcEndpointDesc.commAddr, srcInterface->GetAddr())); | 300 | CHK_RET(SetCommAddress(commLink.srcEndpointDesc.commAddr, srcInterface->GetAddr())); |
| 299 | CHK_RET(SetEndpointLoc(commLink.srcEndpointDesc.loc.locType, srcInterface->GetPos())); | 301 | CHK_RET(SetEndpointLoc(commLink.srcEndpointDesc.loc.locType, srcInterface->GetPos())); |
| 302 | + CHK_RET(SetEndpointTopoInfo(commLink.srcEndpointDesc, netLayer, srcInterface->GetTopoInstId())); | ||
| 300 | if (commLink.srcEndpointDesc.loc.locType == ENDPOINT_LOC_TYPE_DEVICE) { | 303 | if (commLink.srcEndpointDesc.loc.locType == ENDPOINT_LOC_TYPE_DEVICE) { |
| 301 | std::shared_ptr<NetInstance::Node> srcNode = peer2net->GetSourceNode(); | 304 | std::shared_ptr<NetInstance::Node> srcNode = peer2net->GetSourceNode(); |
| 302 | std::shared_ptr<NetInstance::Peer> srcPeer = std::dynamic_pointer_cast<NetInstance::Peer>(srcNode); | 305 | std::shared_ptr<NetInstance::Peer> srcPeer = std::dynamic_pointer_cast<NetInstance::Peer>(srcNode); |
| @@ -306,6 +309,7 @@ static HcclResult InsertClosLinks(const NetInstance::Path& path, std::vector<Com | |||
| 306 | // 设置目标端点 | 309 | // 设置目标端点 |
| 307 | CHK_RET(SetCommAddress(commLink.dstEndpointDesc.commAddr, dstInterface->GetAddr())); | 310 | CHK_RET(SetCommAddress(commLink.dstEndpointDesc.commAddr, dstInterface->GetAddr())); |
| 308 | CHK_RET(SetEndpointLoc(commLink.dstEndpointDesc.loc.locType, dstInterface->GetPos())); | 311 | CHK_RET(SetEndpointLoc(commLink.dstEndpointDesc.loc.locType, dstInterface->GetPos())); |
| 312 | + CHK_RET(SetEndpointTopoInfo(commLink.dstEndpointDesc, netLayer, dstInterface->GetTopoInstId())); | ||
| 309 | if (commLink.dstEndpointDesc.loc.locType == ENDPOINT_LOC_TYPE_DEVICE) { | 313 | if (commLink.dstEndpointDesc.loc.locType == ENDPOINT_LOC_TYPE_DEVICE) { |
| 310 | std::shared_ptr<NetInstance::Node> dstNode = net2peer->GetTargetNode(); | 314 | std::shared_ptr<NetInstance::Node> dstNode = net2peer->GetTargetNode(); |
| 311 | std::shared_ptr<NetInstance::Peer> dstPeer = std::dynamic_pointer_cast<NetInstance::Peer>(dstNode); | 315 | std::shared_ptr<NetInstance::Peer> dstPeer = std::dynamic_pointer_cast<NetInstance::Peer>(dstNode); |
| @@ -343,7 +347,7 @@ IRankGraph::GetLinks(uint32_t netLayer, uint32_t srcRank, uint32_t dstRank, Comm | |||
| 343 | } | 347 | } |
| 344 | if (!isClos) { | 348 | if (!isClos) { |
| 345 | // Peer2Peer网络:直接处理每条link | 349 | // Peer2Peer网络:直接处理每条link |
| 346 | - HcclResult ret = InsertInnerLink(path, linkListVec_); | 350 | + HcclResult ret = InsertInnerLink(netLayer, path, linkListVec_); |
| 347 | CHK_PRT_RET( | 351 | CHK_PRT_RET( |
| 348 | ret != HCCL_SUCCESS, | 352 | ret != HCCL_SUCCESS, |
| 349 | HCCL_ERROR( | 353 | HCCL_ERROR( |
| @@ -352,7 +356,7 @@ IRankGraph::GetLinks(uint32_t netLayer, uint32_t srcRank, uint32_t dstRank, Comm | |||
| 352 | ret); | 356 | ret); |
| 353 | } else { | 357 | } else { |
| 354 | // Clos网络:找到peer2net和net2peer,组合成一条链路 | 358 | // Clos网络:找到peer2net和net2peer,组合成一条链路 |
| 355 | - HcclResult ret = InsertClosLinks(path, linkListVec_); | 359 | + HcclResult ret = InsertClosLinks(netLayer, path, linkListVec_); |
| 356 | CHK_PRT_RET( | 360 | CHK_PRT_RET( |
| 357 | ret != HCCL_SUCCESS, | 361 | ret != HCCL_SUCCESS, |
| 358 | HCCL_ERROR( | 362 | HCCL_ERROR( |
| @@ -16,7 +16,7 @@ | |||
| 16 | { | 16 | { |
| 17 | "addr_type": "IPV4", | 17 | "addr_type": "IPV4", |
| 18 | "addr": "223.0.0.28", | 18 | "addr": "223.0.0.28", |
| 19 | - "ports": [ "0/0" ] | 19 | + "ports": [ "0/2" ] |
| 20 | } | 20 | } |
| 21 | ] | 21 | ] |
| 22 | } | 22 | } |
| @@ -36,7 +36,7 @@ | |||
| 36 | { | 36 | { |
| 37 | "addr_type": "IPV4", | 37 | "addr_type": "IPV4", |
| 38 | "addr": "223.0.0.10", | 38 | "addr": "223.0.0.10", |
| 39 | - "ports": [ "0/1" ] | 39 | + "ports": [ "0/5" ] |
| 40 | } | 40 | } |
| 41 | ] | 41 | ] |
| 42 | } | 42 | } |
| @@ -16,7 +16,7 @@ | |||
| 16 | { | 16 | { |
| 17 | "addr_type": "IPV4", | 17 | "addr_type": "IPV4", |
| 18 | "addr": "223.0.0.10", | 18 | "addr": "223.0.0.10", |
| 19 | - "ports": [ "0/0" ] | 19 | + "ports": [ "1/1", "0/1" ] |
| 20 | },{ | 20 | },{ |
| 21 | "addr_type": "IPV4", | 21 | "addr_type": "IPV4", |
| 22 | "addr": "223.0.0.15", | 22 | "addr": "223.0.0.15", |
| @@ -41,7 +41,7 @@ | |||
| 41 | { | 41 | { |
| 42 | "addr_type": "IPV4", | 42 | "addr_type": "IPV4", |
| 43 | "addr": "223.0.0.28", | 43 | "addr": "223.0.0.28", |
| 44 | - "ports": [ "0/0" ] | 44 | + "ports": [ "1/7", "0/2" ] |
| 45 | },{ | 45 | },{ |
| 46 | "addr_type": "IPV4", | 46 | "addr_type": "IPV4", |
| 47 | "addr": "223.0.0.33", | 47 | "addr": "223.0.0.33", |
| @@ -66,7 +66,7 @@ | |||
| 66 | { | 66 | { |
| 67 | "addr_type": "IPV4", | 67 | "addr_type": "IPV4", |
| 68 | "addr": "223.0.1.10", | 68 | "addr": "223.0.1.10", |
| 69 | - "ports": [ "0/0" ] | 69 | + "ports": [ "0/1", "1/1" ] |
| 70 | },{ | 70 | },{ |
| 71 | "addr_type": "IPV4", | 71 | "addr_type": "IPV4", |
| 72 | "addr": "223.0.1.15", | 72 | "addr": "223.0.1.15", |
| @@ -92,7 +92,7 @@ | |||
| 92 | { | 92 | { |
| 93 | "addr_type": "IPV4", | 93 | "addr_type": "IPV4", |
| 94 | "addr": "223.0.1.28", | 94 | "addr": "223.0.1.28", |
| 95 | - "ports": [ "0/0" ] | 95 | + "ports": [ "0/2", "1/7" ] |
| 96 | },{ | 96 | },{ |
| 97 | "addr_type": "IPV4", | 97 | "addr_type": "IPV4", |
| 98 | "addr": "223.0.1.33", | 98 | "addr": "223.0.1.33", |
| @@ -176,3 +176,17 @@ HcclResult HrtRaGetTpAttrAsync( | |||
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | } // namespace Hccl | 178 | } // namespace Hccl |
| 179 | + | ||
| 180 | +// legacy ST 会调用 base_comm 的协议查询逻辑,此处模拟设备支持 CTP。 | ||
| 181 | +namespace hcomm { | ||
| 182 | + | ||
| 183 | +HcclResult HccpRaGetDevBaseAttr(void* ctxHandle, struct DevBaseAttr* attr) | ||
| 184 | +{ | ||
| 185 | + (void)ctxHandle; | ||
| 186 | + if (attr != nullptr) { | ||
| 187 | + attr->ub.priorityInfo[0].tpType.bs.ctp = 1; | ||
| 188 | + } | ||
| 189 | + return HCCL_SUCCESS; | ||
| 190 | +} | ||
| 191 | + | ||
| 192 | +} // namespace hcomm | ||
| @@ -214,34 +214,26 @@ protected: | |||
| 214 | void TearDown() override {} | 214 | void TearDown() override {} |
| 215 | }; | 215 | }; |
| 216 | 216 | ||
| 217 | -TEST_F(PhyTopoTest, St_AddTopoGraph_When_TopoNotNullAndNetLayerNotExist_Expect_ReturnTopo) | 217 | +TEST_F(PhyTopoTest, St_AddTopoGraph_When_TopoNotNull_Expect_ReturnTopo) |
| 218 | { | 218 | { |
| 219 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | 219 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); |
| 220 | - u32 netLayer = 1; | 220 | + phyTopo.AddTopoGraph(topo); |
| 221 | - phyTopo.AddTopoGraph(netLayer, topo); | 221 | + EXPECT_EQ(phyTopo.GetTopoGraph(), topo); |
| 222 | - EXPECT_EQ(phyTopo.GetTopoGraph(netLayer), topo); | ||
| 223 | } | 222 | } |
| 224 | 223 | ||
| 225 | -TEST_F(PhyTopoTest, St_GetTopoGraph_When_NetLayerExist_Expect_ReturnTopo) | 224 | +TEST_F(PhyTopoTest, St_GetTopoGraph_When_TopoNotAdded_Expect_ReturnNullptr) |
| 226 | { | 225 | { |
| 227 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo1 | 226 | + EXPECT_EQ(phyTopo.GetTopoGraph(), nullptr); |
| 228 | - = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | ||
| 229 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo2 | ||
| 230 | - = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | ||
| 231 | - u32 netLayer1 = 1; | ||
| 232 | - u32 netLayer2 = 2; | ||
| 233 | - phyTopo.AddTopoGraph(netLayer1, topo1); | ||
| 234 | - phyTopo.AddTopoGraph(netLayer2, topo2); | ||
| 235 | - EXPECT_EQ(phyTopo.GetTopoGraph(netLayer1), topo1); | ||
| 236 | - EXPECT_EQ(phyTopo.GetTopoGraph(netLayer2), topo2); | ||
| 237 | } | 227 | } |
| 238 | 228 | ||
| 239 | -TEST_F(PhyTopoTest, St_GetTopoGraph_When_NetLayerNoExist_Expect_ReturnNullptr) | 229 | +TEST_F(PhyTopoTest, St_Clear_When_TopoAdded_Expect_ResetTopoAndInitFlag) |
| 240 | { | 230 | { |
| 241 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo1 | 231 | + std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); |
| 242 | - = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | 232 | + phyTopo.AddTopoGraph(topo); |
| 243 | - u32 netLayer1 = 1; | 233 | + phyTopo.InitFinish(); |
| 244 | - u32 netLayer2 = 2; | 234 | + |
| 245 | - phyTopo.AddTopoGraph(netLayer1, topo1); | 235 | + phyTopo.Clear(); |
| 246 | - EXPECT_EQ(phyTopo.GetTopoGraph(netLayer2), nullptr); | 236 | + |
| 237 | + EXPECT_EQ(phyTopo.GetTopoGraph(), nullptr); | ||
| 238 | + EXPECT_FALSE(phyTopo.IsInitFinished()); | ||
| 247 | } | 239 | } |
| @@ -214,13 +214,8 @@ std::unique_ptr<PhyTopo> PhyTopoBuilderBuildStub(const std::string& topoPath) | |||
| 214 | std::unique_ptr<PhyTopo> phyTopo = std::make_unique<PhyTopo>(); | 214 | std::unique_ptr<PhyTopo> phyTopo = std::make_unique<PhyTopo>(); |
| 215 | PhyTopoBuilder phyTopoBuilder; | 215 | PhyTopoBuilder phyTopoBuilder; |
| 216 | auto topoInfo = phyTopoBuilder.LoadTopoInfo(topoPath); | 216 | auto topoInfo = phyTopoBuilder.LoadTopoInfo(topoPath); |
| 217 | - // 根据topoInfo,按netLayer构造Graph | 217 | + auto graph = phyTopoBuilder.CreateGraph(topoInfo->edges); |
| 218 | - for (const auto& iter : topoInfo->edges) { | 218 | + phyTopo->AddTopoGraph(graph); |
| 219 | - auto netLayer = iter.first; | ||
| 220 | - auto graph = phyTopoBuilder.CreateGraph(iter.second); | ||
| 221 | - phyTopo->AddTopoGraph(netLayer, graph); | ||
| 222 | - HCCL_DEBUG("[PhyTopoBuilder::%s]Build netLayer[%u] topo graph success.", __func__, netLayer); | ||
| 223 | - } | ||
| 224 | return phyTopo; | 219 | return phyTopo; |
| 225 | } | 220 | } |
| 226 | 221 | ||
| @@ -268,7 +263,7 @@ TEST_F(PhyTopoBuilderTest, St_PhyTopoBuilder_When_ValidTopoPath_Expect_ReturnEdg | |||
| 268 | std::string topoPath = "./topo.json"; | 263 | std::string topoPath = "./topo.json"; |
| 269 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoStub)); | 264 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoStub)); |
| 270 | std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); | 265 | std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); |
| 271 | - auto graph = phyTopo->GetTopoGraph(0); | 266 | + auto graph = phyTopo->GetTopoGraph(); |
| 272 | size_t totalEdgeNum = 0; | 267 | size_t totalEdgeNum = 0; |
| 273 | 268 | ||
| 274 | // 遍历所有源节点 | 269 | // 遍历所有源节点 |
| @@ -296,7 +291,7 @@ TEST_F(PhyTopoBuilderTest, St_PhyTopoBuilder_When_DiffProtocols_Expect_ReturnEdg | |||
| 296 | std::string topoPath = "./topo.json"; | 291 | std::string topoPath = "./topo.json"; |
| 297 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoWithDiffProtocols)); | 292 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoWithDiffProtocols)); |
| 298 | std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); | 293 | std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); |
| 299 | - auto graph = phyTopo->GetTopoGraph(0); | 294 | + auto graph = phyTopo->GetTopoGraph(); |
| 300 | size_t totalEdgeNum = 0; | 295 | size_t totalEdgeNum = 0; |
| 301 | 296 | ||
| 302 | // 遍历所有源节点 | 297 | // 遍历所有源节点 |
| @@ -40,7 +40,6 @@ TEST_F(EdgeParserTest, St_Deserialize_When_Normal_Expect_Success) | |||
| 40 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); | 40 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); |
| 41 | 41 | ||
| 42 | std::string edgeString = R"({ | 42 | std::string edgeString = R"({ |
| 43 | - "net_layer": 0, | ||
| 44 | "link_type": "PEER2PEER", | 43 | "link_type": "PEER2PEER", |
| 45 | "protocols": ["UB_CTP"], | 44 | "protocols": ["UB_CTP"], |
| 46 | "topo_type": "1DMESH", | 45 | "topo_type": "1DMESH", |
| @@ -57,7 +56,6 @@ TEST_F(EdgeParserTest, St_Deserialize_When_Normal_Expect_Success) | |||
| 57 | topoParser.ParseString(edgeString, edgeInfo); | 56 | topoParser.ParseString(edgeString, edgeInfo); |
| 58 | 57 | ||
| 59 | EdgeInfo edge0; | 58 | EdgeInfo edge0; |
| 60 | - edge0.netLayer = 0; | ||
| 61 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 59 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 62 | edge0.linkType = LinkType::PEER2PEER; | 60 | edge0.linkType = LinkType::PEER2PEER; |
| 63 | edge0.topoType = TopoType::MESH_1D; | 61 | edge0.topoType = TopoType::MESH_1D; |
| @@ -93,7 +91,6 @@ TEST_F(EdgeParserTest, St_Deserialize_When_OptionalFieldsMissing_Expect_Success) | |||
| 93 | topoParser.ParseString(edgeString, edgeInfo); | 91 | topoParser.ParseString(edgeString, edgeInfo); |
| 94 | 92 | ||
| 95 | EdgeInfo edge0; | 93 | EdgeInfo edge0; |
| 96 | - edge0.netLayer = 0; | ||
| 97 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 94 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 98 | edge0.linkType = LinkType::PEER2PEER; | 95 | edge0.linkType = LinkType::PEER2PEER; |
| 99 | edge0.topoType = TopoType::CLOS; | 96 | edge0.topoType = TopoType::CLOS; |
| @@ -131,7 +128,6 @@ TEST_F(EdgeParserTest, St_Deserialize_When_PEER2NET_ExistB_Expect_Warning) | |||
| 131 | topoParser.ParseString(edgeString, edgeInfo); | 128 | topoParser.ParseString(edgeString, edgeInfo); |
| 132 | 129 | ||
| 133 | EdgeInfo edge0; | 130 | EdgeInfo edge0; |
| 134 | - edge0.netLayer = 0; | ||
| 135 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 131 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 136 | edge0.linkType = LinkType::PEER2NET; | 132 | edge0.linkType = LinkType::PEER2NET; |
| 137 | edge0.topoType = TopoType::MESH_1D; | 133 | edge0.topoType = TopoType::MESH_1D; |
| @@ -165,7 +161,6 @@ TEST_F(EdgeParserTest, St_Deserialize_When_NormalPeer2Net_Expect_Success) | |||
| 165 | topoParser.ParseString(edgeString, edgeInfo); | 161 | topoParser.ParseString(edgeString, edgeInfo); |
| 166 | 162 | ||
| 167 | EdgeInfo edge0; | 163 | EdgeInfo edge0; |
| 168 | - edge0.netLayer = 0; | ||
| 169 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 164 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 170 | edge0.linkType = LinkType::PEER2NET; | 165 | edge0.linkType = LinkType::PEER2NET; |
| 171 | edge0.topoType = TopoType::MESH_1D; | 166 | edge0.topoType = TopoType::MESH_1D; |
| @@ -194,14 +189,13 @@ TEST_F(EdgeParserTest, St_Deserialize_When_NeededFieldMissing_Expect_Exception) | |||
| 194 | EXPECT_THROW(edgeParser.ParseString(edgeString, edgeInfo), InvalidParamsException); | 189 | EXPECT_THROW(edgeParser.ParseString(edgeString, edgeInfo), InvalidParamsException); |
| 195 | } | 190 | } |
| 196 | 191 | ||
| 197 | -// net_layer = 8 | 192 | +// 旧 topo.json 中不同或越界的 net_layer 都应被忽略,解析结果与不带该字段时一致 |
| 198 | -TEST_F(EdgeParserTest, St_Deserialize_When_InvalidNetLayer_Expect_Exception) | 193 | +TEST_F(EdgeParserTest, St_Deserialize_When_LegacyNetLayerDifferentOrOutOfRange_Expect_SameEdge) |
| 199 | { | 194 | { |
| 200 | DevType devType = DevType::DEV_TYPE_910A; | 195 | DevType devType = DevType::DEV_TYPE_910A; |
| 201 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); | 196 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); |
| 202 | 197 | ||
| 203 | - std::string edgeString = R"({ | 198 | + std::string edgeStringWithoutNetLayer = R"({ |
| 204 | - "net_layer": 8, | ||
| 205 | "link_type": "PEER2PEER", | 199 | "link_type": "PEER2PEER", |
| 206 | "protocols": ["UB_CTP"], | 200 | "protocols": ["UB_CTP"], |
| 207 | "topo_type": "1DMESH", | 201 | "topo_type": "1DMESH", |
| @@ -213,9 +207,21 @@ TEST_F(EdgeParserTest, St_Deserialize_When_InvalidNetLayer_Expect_Exception) | |||
| 213 | "position": "DEVICE" | 207 | "position": "DEVICE" |
| 214 | })"; | 208 | })"; |
| 215 | 209 | ||
| 210 | + nlohmann::json edgeJsonWithoutNetLayer = nlohmann::json::parse(edgeStringWithoutNetLayer); | ||
| 211 | + nlohmann::json edgeJsonWithDifferentNetLayer = edgeJsonWithoutNetLayer; | ||
| 212 | + nlohmann::json edgeJsonWithOutOfRangeNetLayer = edgeJsonWithoutNetLayer; | ||
| 213 | + edgeJsonWithDifferentNetLayer["net_layer"] = 1; | ||
| 214 | + edgeJsonWithOutOfRangeNetLayer["net_layer"] = 8; | ||
| 215 | + | ||
| 216 | JsonParser edgeParser; | 216 | JsonParser edgeParser; |
| 217 | - EdgeInfo edgeInfo; | 217 | + EdgeInfo edgeWithoutNetLayer; |
| 218 | - EXPECT_THROW(edgeParser.ParseString(edgeString, edgeInfo), InvalidParamsException); | 218 | + EdgeInfo edgeWithDifferentNetLayer; |
| 219 | + EdgeInfo edgeWithOutOfRangeNetLayer; | ||
| 220 | + EXPECT_NO_THROW(edgeParser.ParseString(edgeStringWithoutNetLayer, edgeWithoutNetLayer)); | ||
| 221 | + EXPECT_NO_THROW(edgeParser.ParseString(edgeJsonWithDifferentNetLayer.dump(), edgeWithDifferentNetLayer)); | ||
| 222 | + EXPECT_NO_THROW(edgeParser.ParseString(edgeJsonWithOutOfRangeNetLayer.dump(), edgeWithOutOfRangeNetLayer)); | ||
| 223 | + EXPECT_TRUE(edgeWithoutNetLayer == edgeWithDifferentNetLayer); | ||
| 224 | + EXPECT_TRUE(edgeWithoutNetLayer == edgeWithOutOfRangeNetLayer); | ||
| 219 | } | 225 | } |
| 220 | 226 | ||
| 221 | // 无效的LinkProtocol | 227 | // 无效的LinkProtocol |
| @@ -266,7 +272,6 @@ TEST_F(EdgeParserTest, St_Deserialize_When_ToManyLinkProtocols_Expect_Exception) | |||
| 266 | edgeParser.ParseString(edgeString, edgeInfo); | 272 | edgeParser.ParseString(edgeString, edgeInfo); |
| 267 | 273 | ||
| 268 | EdgeInfo edge0; | 274 | EdgeInfo edge0; |
| 269 | - edge0.netLayer = 2; | ||
| 270 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 275 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 271 | edge0.protocols.emplace(LinkProtocol::ROCE); | 276 | edge0.protocols.emplace(LinkProtocol::ROCE); |
| 272 | edge0.linkType = LinkType::PEER2PEER; | 277 | edge0.linkType = LinkType::PEER2PEER; |
| @@ -426,7 +431,6 @@ TEST_F(EdgeParserTest, St_Deserialize_When_InvalidPosition_Expect_Exception) | |||
| 426 | TEST_F(EdgeParserTest, St_BinaryStream_When_GetBinStreamToReBuild_Expect_Success) | 431 | TEST_F(EdgeParserTest, St_BinaryStream_When_GetBinStreamToReBuild_Expect_Success) |
| 427 | { | 432 | { |
| 428 | EdgeInfo edge0; | 433 | EdgeInfo edge0; |
| 429 | - edge0.netLayer = 0; | ||
| 430 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 434 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 431 | edge0.linkType = LinkType::PEER2PEER; | 435 | edge0.linkType = LinkType::PEER2PEER; |
| 432 | edge0.topoType = TopoType::MESH_1D; | 436 | edge0.topoType = TopoType::MESH_1D; |
| @@ -126,11 +126,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 126 | expectTopoInfo.peers.emplace_back(peer2); | 126 | expectTopoInfo.peers.emplace_back(peer2); |
| 127 | 127 | ||
| 128 | expectTopoInfo.edgeCount = 5; | 128 | expectTopoInfo.edgeCount = 5; |
| 129 | - expectTopoInfo.edges[0] = std::vector<EdgeInfo>(); | ||
| 130 | - expectTopoInfo.edges[1] = std::vector<EdgeInfo>(); | ||
| 131 | - expectTopoInfo.edges[2] = std::vector<EdgeInfo>(); | ||
| 132 | EdgeInfo edge0; | 129 | EdgeInfo edge0; |
| 133 | - edge0.netLayer = 0; | ||
| 134 | edge0.linkType = LinkType::PEER2PEER; | 130 | edge0.linkType = LinkType::PEER2PEER; |
| 135 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 131 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 136 | edge0.topoType = TopoType::MESH_1D; | 132 | edge0.topoType = TopoType::MESH_1D; |
| @@ -140,10 +136,9 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 140 | edge0.localB = 1; | 136 | edge0.localB = 1; |
| 141 | edge0.localBPorts.emplace("0/1"); | 137 | edge0.localBPorts.emplace("0/1"); |
| 142 | edge0.position = AddrPosition::DEVICE; | 138 | edge0.position = AddrPosition::DEVICE; |
| 143 | - expectTopoInfo.edges[0].emplace_back(edge0); | 139 | + expectTopoInfo.edges.emplace_back(edge0); |
| 144 | 140 | ||
| 145 | EdgeInfo edge1; | 141 | EdgeInfo edge1; |
| 146 | - edge1.netLayer = 0; | ||
| 147 | edge1.linkType = LinkType::PEER2PEER; | 142 | edge1.linkType = LinkType::PEER2PEER; |
| 148 | edge1.protocols.emplace(LinkProtocol::UB_MEM); | 143 | edge1.protocols.emplace(LinkProtocol::UB_MEM); |
| 149 | edge1.topoType = TopoType::MESH_1D; | 144 | edge1.topoType = TopoType::MESH_1D; |
| @@ -153,10 +148,9 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 153 | edge1.localB = 2; | 148 | edge1.localB = 2; |
| 154 | edge1.localBPorts.emplace("0/1"); | 149 | edge1.localBPorts.emplace("0/1"); |
| 155 | edge1.position = AddrPosition::DEVICE; | 150 | edge1.position = AddrPosition::DEVICE; |
| 156 | - expectTopoInfo.edges[0].emplace_back(edge1); | 151 | + expectTopoInfo.edges.emplace_back(edge1); |
| 157 | 152 | ||
| 158 | EdgeInfo edge2; | 153 | EdgeInfo edge2; |
| 159 | - edge2.netLayer = 0; | ||
| 160 | edge2.linkType = LinkType::PEER2NET; | 154 | edge2.linkType = LinkType::PEER2NET; |
| 161 | edge2.protocols.emplace(LinkProtocol::UB_CTP); | 155 | edge2.protocols.emplace(LinkProtocol::UB_CTP); |
| 162 | edge2.topoType = TopoType::MESH_1D; | 156 | edge2.topoType = TopoType::MESH_1D; |
| @@ -164,10 +158,9 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 164 | edge2.localA = 0; | 158 | edge2.localA = 0; |
| 165 | edge2.localAPorts.emplace("0/0"); | 159 | edge2.localAPorts.emplace("0/0"); |
| 166 | edge2.position = AddrPosition::HOST; | 160 | edge2.position = AddrPosition::HOST; |
| 167 | - expectTopoInfo.edges[0].emplace_back(edge2); | 161 | + expectTopoInfo.edges.emplace_back(edge2); |
| 168 | 162 | ||
| 169 | EdgeInfo edge3; | 163 | EdgeInfo edge3; |
| 170 | - edge3.netLayer = 1; | ||
| 171 | edge3.linkType = LinkType::PEER2PEER; | 164 | edge3.linkType = LinkType::PEER2PEER; |
| 172 | edge3.protocols.emplace(LinkProtocol::UB_TP); | 165 | edge3.protocols.emplace(LinkProtocol::UB_TP); |
| 173 | edge3.topoType = TopoType::MESH_1D; | 166 | edge3.topoType = TopoType::MESH_1D; |
| @@ -177,10 +170,9 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 177 | edge3.localB = 2; | 170 | edge3.localB = 2; |
| 178 | edge3.localBPorts.emplace("0/1"); | 171 | edge3.localBPorts.emplace("0/1"); |
| 179 | edge3.position = AddrPosition::DEVICE; | 172 | edge3.position = AddrPosition::DEVICE; |
| 180 | - expectTopoInfo.edges[1].emplace_back(edge3); | 173 | + expectTopoInfo.edges.emplace_back(edge3); |
| 181 | 174 | ||
| 182 | EdgeInfo edge4; | 175 | EdgeInfo edge4; |
| 183 | - edge4.netLayer = 2; | ||
| 184 | edge4.linkType = LinkType::PEER2NET; | 176 | edge4.linkType = LinkType::PEER2NET; |
| 185 | edge4.protocols.emplace(LinkProtocol::ROCE); | 177 | edge4.protocols.emplace(LinkProtocol::ROCE); |
| 186 | edge4.topoType = TopoType::CLOS; | 178 | edge4.topoType = TopoType::CLOS; |
| @@ -188,7 +180,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 188 | edge4.localA = 0; | 180 | edge4.localA = 0; |
| 189 | edge4.localAPorts.emplace("0/0"); | 181 | edge4.localAPorts.emplace("0/0"); |
| 190 | edge4.position = AddrPosition::DEVICE; | 182 | edge4.position = AddrPosition::DEVICE; |
| 191 | - expectTopoInfo.edges[2].emplace_back(edge4); | 183 | + expectTopoInfo.edges.emplace_back(edge4); |
| 192 | 184 | ||
| 193 | EXPECT_EQ(topoInfo.version, expectTopoInfo.version); | 185 | EXPECT_EQ(topoInfo.version, expectTopoInfo.version); |
| 194 | EXPECT_EQ(topoInfo.peerCount, expectTopoInfo.peerCount); | 186 | EXPECT_EQ(topoInfo.peerCount, expectTopoInfo.peerCount); |
| @@ -199,25 +191,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 199 | EXPECT_EQ(topoInfo.edgeCount, expectTopoInfo.edgeCount); | 191 | EXPECT_EQ(topoInfo.edgeCount, expectTopoInfo.edgeCount); |
| 200 | EXPECT_EQ(topoInfo.edges.size(), expectTopoInfo.edges.size()); | 192 | EXPECT_EQ(topoInfo.edges.size(), expectTopoInfo.edges.size()); |
| 201 | 193 | ||
| 202 | - auto it_topo_edges = topoInfo.edges.begin(); | 194 | + EXPECT_EQ(topoInfo.edges, expectTopoInfo.edges); |
| 203 | - auto it_expect_edges = expectTopoInfo.edges.begin(); | ||
| 204 | - for (; it_topo_edges != topoInfo.edges.end(); it_topo_edges++, it_expect_edges++) { | ||
| 205 | - EXPECT_EQ(it_topo_edges->first, it_expect_edges->first); | ||
| 206 | - EXPECT_EQ((it_topo_edges->second).size(), (it_expect_edges->second).size()); | ||
| 207 | - for (u32 i = 0; i < (it_topo_edges->second).size(); i++) { | ||
| 208 | - EXPECT_EQ((it_topo_edges->second)[i].netLayer, (it_expect_edges->second)[i].netLayer); | ||
| 209 | - EXPECT_EQ((it_topo_edges->second)[i].protocols, (it_expect_edges->second)[i].protocols); | ||
| 210 | - EXPECT_EQ((it_topo_edges->second)[i].linkType, (it_expect_edges->second)[i].linkType); | ||
| 211 | - EXPECT_EQ((it_topo_edges->second)[i].topoType, (it_expect_edges->second)[i].topoType); | ||
| 212 | - EXPECT_EQ((it_topo_edges->second)[i].topoInstId, (it_expect_edges->second)[i].topoInstId); | ||
| 213 | - EXPECT_EQ((it_topo_edges->second)[i].localA, (it_expect_edges->second)[i].localA); | ||
| 214 | - EXPECT_EQ((it_topo_edges->second)[i].localAPorts, (it_expect_edges->second)[i].localAPorts); | ||
| 215 | - EXPECT_EQ((it_topo_edges->second)[i].localB, (it_expect_edges->second)[i].localB); | ||
| 216 | - EXPECT_EQ((it_topo_edges->second)[i].localBPorts, (it_expect_edges->second)[i].localBPorts); | ||
| 217 | - EXPECT_EQ((it_topo_edges->second)[i].position, (it_expect_edges->second)[i].position); | ||
| 218 | - } | ||
| 219 | - } | ||
| 220 | - | ||
| 221 | EXPECT_EQ(topoInfo.Describe(), expectTopoInfo.Describe()); | 195 | EXPECT_EQ(topoInfo.Describe(), expectTopoInfo.Describe()); |
| 222 | } | 196 | } |
| 223 | 197 | ||
| @@ -436,7 +410,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_EdgesSizeUnequalToEdgeCount_Expect_Ex | |||
| 436 | } | 410 | } |
| 437 | 411 | ||
| 438 | // 重复的边 PEER2PEER,localA和localB对调 | 412 | // 重复的边 PEER2PEER,localA和localB对调 |
| 439 | -TEST_F(TopoParserTest, Ut_Deserialize_When_DuplicateEdge_Expect_Exception) | 413 | +TEST_F(TopoParserTest, Ut_Deserialize_When_DuplicateEdge_Expect_Merged) |
| 440 | { | 414 | { |
| 441 | DevType devType = DevType::DEV_TYPE_910A; | 415 | DevType devType = DevType::DEV_TYPE_910A; |
| 442 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); | 416 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); |
| @@ -465,7 +439,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_DuplicateEdge_Expect_Exception) | |||
| 465 | "position": "DEVICE" | 439 | "position": "DEVICE" |
| 466 | }, | 440 | }, |
| 467 | { | 441 | { |
| 468 | - "net_layer": 0, | 442 | + "net_layer": 1, |
| 469 | "link_type": "PEER2PEER", | 443 | "link_type": "PEER2PEER", |
| 470 | "protocols": ["UB_CTP"], | 444 | "protocols": ["UB_CTP"], |
| 471 | "topo_type": "1DMESH", | 445 | "topo_type": "1DMESH", |
| @@ -481,7 +455,11 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_DuplicateEdge_Expect_Exception) | |||
| 481 | 455 | ||
| 482 | JsonParser topoParser; | 456 | JsonParser topoParser; |
| 483 | TopoInfo topoInfo; | 457 | TopoInfo topoInfo; |
| 484 | - EXPECT_THROW(topoParser.ParseString(topoString, topoInfo), InvalidParamsException); | 458 | + EXPECT_NO_THROW(topoParser.ParseString(topoString, topoInfo)); |
| 459 | + EXPECT_EQ(topoInfo.edgeCount, 1); | ||
| 460 | + ASSERT_EQ(topoInfo.edges.size(), 1); | ||
| 461 | + EXPECT_EQ(topoInfo.edges[0].localA, 0); | ||
| 462 | + EXPECT_EQ(topoInfo.edges[0].localB, 1); | ||
| 485 | } | 463 | } |
| 486 | 464 | ||
| 487 | // Endpoint的localId无效 | 465 | // Endpoint的localId无效 |
| @@ -660,11 +638,7 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 660 | expectTopoInfo.peers.emplace_back(peer2); | 638 | expectTopoInfo.peers.emplace_back(peer2); |
| 661 | 639 | ||
| 662 | expectTopoInfo.edgeCount = 5; | 640 | expectTopoInfo.edgeCount = 5; |
| 663 | - expectTopoInfo.edges[0] = std::vector<EdgeInfo>(); | ||
| 664 | - expectTopoInfo.edges[1] = std::vector<EdgeInfo>(); | ||
| 665 | - expectTopoInfo.edges[2] = std::vector<EdgeInfo>(); | ||
| 666 | EdgeInfo edge0; | 641 | EdgeInfo edge0; |
| 667 | - edge0.netLayer = 0; | ||
| 668 | edge0.linkType = LinkType::PEER2PEER; | 642 | edge0.linkType = LinkType::PEER2PEER; |
| 669 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 643 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 670 | edge0.topoType = TopoType::MESH_1D; | 644 | edge0.topoType = TopoType::MESH_1D; |
| @@ -674,10 +648,9 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 674 | edge0.localB = 1; | 648 | edge0.localB = 1; |
| 675 | edge0.localBPorts.emplace("0/1"); | 649 | edge0.localBPorts.emplace("0/1"); |
| 676 | edge0.position = AddrPosition::DEVICE; | 650 | edge0.position = AddrPosition::DEVICE; |
| 677 | - expectTopoInfo.edges[0].emplace_back(edge0); | 651 | + expectTopoInfo.edges.emplace_back(edge0); |
| 678 | 652 | ||
| 679 | EdgeInfo edge1; | 653 | EdgeInfo edge1; |
| 680 | - edge1.netLayer = 0; | ||
| 681 | edge1.linkType = LinkType::PEER2PEER; | 654 | edge1.linkType = LinkType::PEER2PEER; |
| 682 | edge1.protocols.emplace(LinkProtocol::UB_MEM); | 655 | edge1.protocols.emplace(LinkProtocol::UB_MEM); |
| 683 | edge1.topoType = TopoType::MESH_1D; | 656 | edge1.topoType = TopoType::MESH_1D; |
| @@ -687,10 +660,9 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 687 | edge1.localB = 2; | 660 | edge1.localB = 2; |
| 688 | edge1.localBPorts.emplace("0/1"); | 661 | edge1.localBPorts.emplace("0/1"); |
| 689 | edge1.position = AddrPosition::DEVICE; | 662 | edge1.position = AddrPosition::DEVICE; |
| 690 | - expectTopoInfo.edges[0].emplace_back(edge1); | 663 | + expectTopoInfo.edges.emplace_back(edge1); |
| 691 | 664 | ||
| 692 | EdgeInfo edge2; | 665 | EdgeInfo edge2; |
| 693 | - edge2.netLayer = 0; | ||
| 694 | edge2.linkType = LinkType::PEER2NET; | 666 | edge2.linkType = LinkType::PEER2NET; |
| 695 | edge2.protocols.emplace(LinkProtocol::UB_CTP); | 667 | edge2.protocols.emplace(LinkProtocol::UB_CTP); |
| 696 | edge2.topoType = TopoType::MESH_1D; | 668 | edge2.topoType = TopoType::MESH_1D; |
| @@ -698,10 +670,9 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 698 | edge2.localA = 0; | 670 | edge2.localA = 0; |
| 699 | edge2.localAPorts.emplace("0/0"); | 671 | edge2.localAPorts.emplace("0/0"); |
| 700 | edge2.position = AddrPosition::HOST; | 672 | edge2.position = AddrPosition::HOST; |
| 701 | - expectTopoInfo.edges[0].emplace_back(edge2); | 673 | + expectTopoInfo.edges.emplace_back(edge2); |
| 702 | 674 | ||
| 703 | EdgeInfo edge3; | 675 | EdgeInfo edge3; |
| 704 | - edge3.netLayer = 1; | ||
| 705 | edge3.linkType = LinkType::PEER2PEER; | 676 | edge3.linkType = LinkType::PEER2PEER; |
| 706 | edge3.protocols.emplace(LinkProtocol::UB_TP); | 677 | edge3.protocols.emplace(LinkProtocol::UB_TP); |
| 707 | edge3.topoType = TopoType::MESH_1D; | 678 | edge3.topoType = TopoType::MESH_1D; |
| @@ -711,10 +682,9 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 711 | edge3.localB = 2; | 682 | edge3.localB = 2; |
| 712 | edge3.localBPorts.emplace("0/1"); | 683 | edge3.localBPorts.emplace("0/1"); |
| 713 | edge3.position = AddrPosition::DEVICE; | 684 | edge3.position = AddrPosition::DEVICE; |
| 714 | - expectTopoInfo.edges[1].emplace_back(edge3); | 685 | + expectTopoInfo.edges.emplace_back(edge3); |
| 715 | 686 | ||
| 716 | EdgeInfo edge4; | 687 | EdgeInfo edge4; |
| 717 | - edge4.netLayer = 2; | ||
| 718 | edge4.linkType = LinkType::PEER2NET; | 688 | edge4.linkType = LinkType::PEER2NET; |
| 719 | edge4.protocols.emplace(LinkProtocol::ROCE); | 689 | edge4.protocols.emplace(LinkProtocol::ROCE); |
| 720 | edge4.topoType = TopoType::CLOS; | 690 | edge4.topoType = TopoType::CLOS; |
| @@ -722,7 +692,7 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 722 | edge4.localA = 0; | 692 | edge4.localA = 0; |
| 723 | edge4.localAPorts.emplace("0/0"); | 693 | edge4.localAPorts.emplace("0/0"); |
| 724 | edge4.position = AddrPosition::DEVICE; | 694 | edge4.position = AddrPosition::DEVICE; |
| 725 | - expectTopoInfo.edges[2].emplace_back(edge4); | 695 | + expectTopoInfo.edges.emplace_back(edge4); |
| 726 | 696 | ||
| 727 | BinaryStream binStream; | 697 | BinaryStream binStream; |
| 728 | expectTopoInfo.GetBinStream(binStream); | 698 | expectTopoInfo.GetBinStream(binStream); |
| @@ -737,25 +707,7 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 737 | EXPECT_EQ(expectTopoInfo.edgeCount, reBuildTopo.edgeCount); | 707 | EXPECT_EQ(expectTopoInfo.edgeCount, reBuildTopo.edgeCount); |
| 738 | EXPECT_EQ(expectTopoInfo.edges.size(), reBuildTopo.edges.size()); | 708 | EXPECT_EQ(expectTopoInfo.edges.size(), reBuildTopo.edges.size()); |
| 739 | 709 | ||
| 740 | - auto it_topo_edges = expectTopoInfo.edges.begin(); | 710 | + EXPECT_EQ(expectTopoInfo.edges, reBuildTopo.edges); |
| 741 | - auto it_expect_edges = reBuildTopo.edges.begin(); | ||
| 742 | - for (; it_topo_edges != expectTopoInfo.edges.end(); it_topo_edges++, it_expect_edges++) { | ||
| 743 | - EXPECT_EQ(it_topo_edges->first, it_expect_edges->first); | ||
| 744 | - EXPECT_EQ((it_topo_edges->second).size(), (it_expect_edges->second).size()); | ||
| 745 | - for (u32 i = 0; i < (it_topo_edges->second).size(); i++) { | ||
| 746 | - EXPECT_EQ((it_topo_edges->second)[i].netLayer, (it_expect_edges->second)[i].netLayer); | ||
| 747 | - EXPECT_EQ((it_topo_edges->second)[i].protocols, (it_expect_edges->second)[i].protocols); | ||
| 748 | - EXPECT_EQ((it_topo_edges->second)[i].linkType, (it_expect_edges->second)[i].linkType); | ||
| 749 | - EXPECT_EQ((it_topo_edges->second)[i].topoType, (it_expect_edges->second)[i].topoType); | ||
| 750 | - EXPECT_EQ((it_topo_edges->second)[i].topoInstId, (it_expect_edges->second)[i].topoInstId); | ||
| 751 | - EXPECT_EQ((it_topo_edges->second)[i].localA, (it_expect_edges->second)[i].localA); | ||
| 752 | - EXPECT_EQ((it_topo_edges->second)[i].localAPorts, (it_expect_edges->second)[i].localAPorts); | ||
| 753 | - EXPECT_EQ((it_topo_edges->second)[i].localB, (it_expect_edges->second)[i].localB); | ||
| 754 | - EXPECT_EQ((it_topo_edges->second)[i].localBPorts, (it_expect_edges->second)[i].localBPorts); | ||
| 755 | - EXPECT_EQ((it_topo_edges->second)[i].position, (it_expect_edges->second)[i].position); | ||
| 756 | - } | ||
| 757 | - } | ||
| 758 | - | ||
| 759 | EXPECT_EQ(expectTopoInfo.Describe(), reBuildTopo.Describe()); | 711 | EXPECT_EQ(expectTopoInfo.Describe(), reBuildTopo.Describe()); |
| 760 | } | 712 | } |
| 761 | 713 | ||
| @@ -41,21 +41,25 @@ const std::string RankTable2pClos = R"( | |||
| 41 | { | 41 | { |
| 42 | "addr_type": "IPV4", | 42 | "addr_type": "IPV4", |
| 43 | "addr": "192.168.100.11", | 43 | "addr": "192.168.100.11", |
| 44 | + "plane_id": "planeA", | ||
| 44 | "ports": [ "0/1" ] | 45 | "ports": [ "0/1" ] |
| 45 | }, | 46 | }, |
| 46 | { | 47 | { |
| 47 | "addr_type": "IPV4", | 48 | "addr_type": "IPV4", |
| 48 | "addr": "192.168.100.12", | 49 | "addr": "192.168.100.12", |
| 50 | + "plane_id": "planeB", | ||
| 49 | "ports": [ "0/2" ] | 51 | "ports": [ "0/2" ] |
| 50 | }, | 52 | }, |
| 51 | { | 53 | { |
| 52 | "addr_type": "IPV4", | 54 | "addr_type": "IPV4", |
| 53 | "addr": "192.168.100.13", | 55 | "addr": "192.168.100.13", |
| 56 | + "plane_id": "planeC", | ||
| 54 | "ports": [ "0/3" ] | 57 | "ports": [ "0/3" ] |
| 55 | }, | 58 | }, |
| 56 | { | 59 | { |
| 57 | "addr_type": "IPV4", | 60 | "addr_type": "IPV4", |
| 58 | "addr": "192.168.100.14", | 61 | "addr": "192.168.100.14", |
| 62 | + "plane_id": "planeD", | ||
| 59 | "ports": [ "0/4" ] | 63 | "ports": [ "0/4" ] |
| 60 | } | 64 | } |
| 61 | ], | 65 | ], |
| @@ -88,21 +92,25 @@ const std::string RankTable2pClos = R"( | |||
| 88 | { | 92 | { |
| 89 | "addr_type": "IPV4", | 93 | "addr_type": "IPV4", |
| 90 | "addr": "192.168.100.21", | 94 | "addr": "192.168.100.21", |
| 95 | + "plane_id": "planeA", | ||
| 91 | "ports": [ "1/1" ] | 96 | "ports": [ "1/1" ] |
| 92 | }, | 97 | }, |
| 93 | { | 98 | { |
| 94 | "addr_type": "IPV4", | 99 | "addr_type": "IPV4", |
| 95 | "addr": "192.168.100.22", | 100 | "addr": "192.168.100.22", |
| 101 | + "plane_id": "planeB", | ||
| 96 | "ports": [ "1/2" ] | 102 | "ports": [ "1/2" ] |
| 97 | }, | 103 | }, |
| 98 | { | 104 | { |
| 99 | "addr_type": "IPV4", | 105 | "addr_type": "IPV4", |
| 100 | "addr": "192.168.100.23", | 106 | "addr": "192.168.100.23", |
| 107 | + "plane_id": "planeC", | ||
| 101 | "ports": [ "1/3" ] | 108 | "ports": [ "1/3" ] |
| 102 | }, | 109 | }, |
| 103 | { | 110 | { |
| 104 | "addr_type": "IPV4", | 111 | "addr_type": "IPV4", |
| 105 | "addr": "192.168.100.24", | 112 | "addr": "192.168.100.24", |
| 113 | + "plane_id": "planeD", | ||
| 106 | "ports": [ "1/4" ] | 114 | "ports": [ "1/4" ] |
| 107 | } | 115 | } |
| 108 | ], | 116 | ], |
| @@ -142,11 +150,13 @@ const std::string RANK_TABLE_4P_REPLACE_RANK1 = R"( | |||
| 142 | { | 150 | { |
| 143 | "addr_type": "IPV4", | 151 | "addr_type": "IPV4", |
| 144 | "addr": "192.168.164.101", | 152 | "addr": "192.168.164.101", |
| 153 | + "plane_id": "planeA", | ||
| 145 | "ports": [ "0/1" ] | 154 | "ports": [ "0/1" ] |
| 146 | }, | 155 | }, |
| 147 | { | 156 | { |
| 148 | "addr_type": "IPV4", | 157 | "addr_type": "IPV4", |
| 149 | "addr": "192.168.164.102", | 158 | "addr": "192.168.164.102", |
| 159 | + "plane_id": "planeB", | ||
| 150 | "ports": [ "0/2" ] | 160 | "ports": [ "0/2" ] |
| 151 | }, | 161 | }, |
| 152 | { | 162 | { |
| @@ -187,11 +197,13 @@ const std::string RANK_TABLE_4P_REPLACE_RANK1 = R"( | |||
| 187 | { | 197 | { |
| 188 | "addr_type": "IPV4", | 198 | "addr_type": "IPV4", |
| 189 | "addr": "192.168.164.111", | 199 | "addr": "192.168.164.111", |
| 200 | + "plane_id": "planeC", | ||
| 190 | "ports": [ "1/1" ] | 201 | "ports": [ "1/1" ] |
| 191 | }, | 202 | }, |
| 192 | { | 203 | { |
| 193 | "addr_type": "IPV4", | 204 | "addr_type": "IPV4", |
| 194 | "addr": "192.168.164.112", | 205 | "addr": "192.168.164.112", |
| 206 | + "plane_id": "planeD", | ||
| 195 | "ports": [ "1/2" ] | 207 | "ports": [ "1/2" ] |
| 196 | }, | 208 | }, |
| 197 | { | 209 | { |
| @@ -243,41 +255,49 @@ const std::string RANK_TABLE_4P_REPLACE_RANK1 = R"( | |||
| 243 | { | 255 | { |
| 244 | "addr_type": "IPV4", | 256 | "addr_type": "IPV4", |
| 245 | "addr": "192.168.164.100", | 257 | "addr": "192.168.164.100", |
| 258 | + "plane_id": "planeA", | ||
| 246 | "ports": [ "0/0" ] | 259 | "ports": [ "0/0" ] |
| 247 | }, | 260 | }, |
| 248 | { | 261 | { |
| 249 | "addr_type": "IPV4", | 262 | "addr_type": "IPV4", |
| 250 | "addr": "192.168.164.101", | 263 | "addr": "192.168.164.101", |
| 264 | + "plane_id": "planeA", | ||
| 251 | "ports": [ "0/1" ] | 265 | "ports": [ "0/1" ] |
| 252 | }, | 266 | }, |
| 253 | { | 267 | { |
| 254 | "addr_type": "IPV4", | 268 | "addr_type": "IPV4", |
| 255 | "addr": "192.168.164.102", | 269 | "addr": "192.168.164.102", |
| 270 | + "plane_id": "planeA", | ||
| 256 | "ports": [ "0/2" ] | 271 | "ports": [ "0/2" ] |
| 257 | }, | 272 | }, |
| 258 | { | 273 | { |
| 259 | "addr_type": "IPV4", | 274 | "addr_type": "IPV4", |
| 260 | "addr": "192.168.164.103", | 275 | "addr": "192.168.164.103", |
| 276 | + "plane_id": "planeA", | ||
| 261 | "ports": [ "0/3" ] | 277 | "ports": [ "0/3" ] |
| 262 | }, | 278 | }, |
| 263 | { | 279 | { |
| 264 | "addr_type": "IPV4", | 280 | "addr_type": "IPV4", |
| 265 | "addr": "192.168.164.104", | 281 | "addr": "192.168.164.104", |
| 282 | + "plane_id": "planeB", | ||
| 266 | "ports": [ "0/4" ] | 283 | "ports": [ "0/4" ] |
| 267 | }, | 284 | }, |
| 268 | { | 285 | { |
| 269 | "addr_type": "IPV4", | 286 | "addr_type": "IPV4", |
| 270 | "addr": "192.168.164.105", | 287 | "addr": "192.168.164.105", |
| 288 | + "plane_id": "planeB", | ||
| 271 | "ports": [ "0/5" ] | 289 | "ports": [ "0/5" ] |
| 272 | }, | 290 | }, |
| 273 | { | 291 | { |
| 274 | "addr_type": "IPV4", | 292 | "addr_type": "IPV4", |
| 275 | "addr": "192.168.164.106", | 293 | "addr": "192.168.164.106", |
| 294 | + "plane_id": "planeB", | ||
| 276 | "ports": [ "0/6" ] | 295 | "ports": [ "0/6" ] |
| 277 | }, | 296 | }, |
| 278 | { | 297 | { |
| 279 | "addr_type": "IPV4", | 298 | "addr_type": "IPV4", |
| 280 | "addr": "192.168.164.107", | 299 | "addr": "192.168.164.107", |
| 300 | + "plane_id": "planeB", | ||
| 281 | "ports": [ "0/7" ] | 301 | "ports": [ "0/7" ] |
| 282 | }, | 302 | }, |
| 283 | { | 303 | { |
| @@ -288,41 +308,49 @@ const std::string RANK_TABLE_4P_REPLACE_RANK1 = R"( | |||
| 288 | { | 308 | { |
| 289 | "addr_type": "IPV4", | 309 | "addr_type": "IPV4", |
| 290 | "addr": "192.168.164.110", | 310 | "addr": "192.168.164.110", |
| 311 | + "plane_id": "planeC", | ||
| 291 | "ports": [ "1/0" ] | 312 | "ports": [ "1/0" ] |
| 292 | }, | 313 | }, |
| 293 | { | 314 | { |
| 294 | "addr_type": "IPV4", | 315 | "addr_type": "IPV4", |
| 295 | "addr": "192.168.164.111", | 316 | "addr": "192.168.164.111", |
| 317 | + "plane_id": "planeC", | ||
| 296 | "ports": [ "1/1" ] | 318 | "ports": [ "1/1" ] |
| 297 | }, | 319 | }, |
| 298 | { | 320 | { |
| 299 | "addr_type": "IPV4", | 321 | "addr_type": "IPV4", |
| 300 | "addr": "192.168.164.112", | 322 | "addr": "192.168.164.112", |
| 323 | + "plane_id": "planeC", | ||
| 301 | "ports": [ "1/2" ] | 324 | "ports": [ "1/2" ] |
| 302 | }, | 325 | }, |
| 303 | { | 326 | { |
| 304 | "addr_type": "IPV4", | 327 | "addr_type": "IPV4", |
| 305 | "addr": "192.168.164.113", | 328 | "addr": "192.168.164.113", |
| 329 | + "plane_id": "planeC", | ||
| 306 | "ports": [ "1/3" ] | 330 | "ports": [ "1/3" ] |
| 307 | }, | 331 | }, |
| 308 | { | 332 | { |
| 309 | "addr_type": "IPV4", | 333 | "addr_type": "IPV4", |
| 310 | "addr": "192.168.164.114", | 334 | "addr": "192.168.164.114", |
| 335 | + "plane_id": "planeD", | ||
| 311 | "ports": [ "1/4" ] | 336 | "ports": [ "1/4" ] |
| 312 | }, | 337 | }, |
| 313 | { | 338 | { |
| 314 | "addr_type": "IPV4", | 339 | "addr_type": "IPV4", |
| 315 | "addr": "192.168.164.115", | 340 | "addr": "192.168.164.115", |
| 341 | + "plane_id": "planeD", | ||
| 316 | "ports": [ "1/5" ] | 342 | "ports": [ "1/5" ] |
| 317 | }, | 343 | }, |
| 318 | { | 344 | { |
| 319 | "addr_type": "IPV4", | 345 | "addr_type": "IPV4", |
| 320 | "addr": "192.168.164.116", | 346 | "addr": "192.168.164.116", |
| 347 | + "plane_id": "planeD", | ||
| 321 | "ports": [ "1/6" ] | 348 | "ports": [ "1/6" ] |
| 322 | }, | 349 | }, |
| 323 | { | 350 | { |
| 324 | "addr_type": "IPV4", | 351 | "addr_type": "IPV4", |
| 325 | "addr": "192.168.164.117", | 352 | "addr": "192.168.164.117", |
| 353 | + "plane_id": "planeD", | ||
| 326 | "ports": [ "1/7" ] | 354 | "ports": [ "1/7" ] |
| 327 | }, | 355 | }, |
| 328 | { | 356 | { |
| @@ -353,11 +381,13 @@ const std::string RANK_TABLE_4P_REPLACE_RANK1 = R"( | |||
| 353 | { | 381 | { |
| 354 | "addr_type": "IPV4", | 382 | "addr_type": "IPV4", |
| 355 | "addr": "192.168.164.101", | 383 | "addr": "192.168.164.101", |
| 384 | + "plane_id": "planeA", | ||
| 356 | "ports": [ "0/1" ] | 385 | "ports": [ "0/1" ] |
| 357 | }, | 386 | }, |
| 358 | { | 387 | { |
| 359 | "addr_type": "IPV4", | 388 | "addr_type": "IPV4", |
| 360 | "addr": "192.168.164.102", | 389 | "addr": "192.168.164.102", |
| 390 | + "plane_id": "planeB", | ||
| 361 | "ports": [ "0/2" ] | 391 | "ports": [ "0/2" ] |
| 362 | }, | 392 | }, |
| 363 | { | 393 | { |
| @@ -398,11 +428,13 @@ const std::string RANK_TABLE_4P_REPLACE_RANK1 = R"( | |||
| 398 | { | 428 | { |
| 399 | "addr_type": "IPV4", | 429 | "addr_type": "IPV4", |
| 400 | "addr": "192.168.164.111", | 430 | "addr": "192.168.164.111", |
| 431 | + "plane_id": "planeC", | ||
| 401 | "ports": [ "1/1" ] | 432 | "ports": [ "1/1" ] |
| 402 | }, | 433 | }, |
| 403 | { | 434 | { |
| 404 | "addr_type": "IPV4", | 435 | "addr_type": "IPV4", |
| 405 | "addr": "192.168.164.112", | 436 | "addr": "192.168.164.112", |
| 437 | + "plane_id": "planeD", | ||
| 406 | "ports": [ "1/2" ] | 438 | "ports": [ "1/2" ] |
| 407 | }, | 439 | }, |
| 408 | { | 440 | { |
| @@ -458,11 +490,13 @@ const std::string RANK_TABLE_4P_REPLACE_RANK1 = R"( | |||
| 458 | { | 490 | { |
| 459 | "addr_type": "IPV4", | 491 | "addr_type": "IPV4", |
| 460 | "addr": "192.168.164.101", | 492 | "addr": "192.168.164.101", |
| 493 | + "plane_id": "planeA", | ||
| 461 | "ports": [ "0/1" ] | 494 | "ports": [ "0/1" ] |
| 462 | }, | 495 | }, |
| 463 | { | 496 | { |
| 464 | "addr_type": "IPV4", | 497 | "addr_type": "IPV4", |
| 465 | "addr": "192.168.164.102", | 498 | "addr": "192.168.164.102", |
| 499 | + "plane_id": "planeB", | ||
| 466 | "ports": [ "0/2" ] | 500 | "ports": [ "0/2" ] |
| 467 | }, | 501 | }, |
| 468 | { | 502 | { |
| @@ -503,11 +537,13 @@ const std::string RANK_TABLE_4P_REPLACE_RANK1 = R"( | |||
| 503 | { | 537 | { |
| 504 | "addr_type": "IPV4", | 538 | "addr_type": "IPV4", |
| 505 | "addr": "192.168.164.111", | 539 | "addr": "192.168.164.111", |
| 540 | + "plane_id": "planeC", | ||
| 506 | "ports": [ "1/1" ] | 541 | "ports": [ "1/1" ] |
| 507 | }, | 542 | }, |
| 508 | { | 543 | { |
| 509 | "addr_type": "IPV4", | 544 | "addr_type": "IPV4", |
| 510 | "addr": "192.168.164.112", | 545 | "addr": "192.168.164.112", |
| 546 | + "plane_id": "planeD", | ||
| 511 | "ports": [ "1/2" ] | 547 | "ports": [ "1/2" ] |
| 512 | }, | 548 | }, |
| 513 | { | 549 | { |
| @@ -34,6 +34,7 @@ protected: | |||
| 34 | 34 | ||
| 35 | virtual void SetUp() | 35 | virtual void SetUp() |
| 36 | { | 36 | { |
| 37 | + PhyTopo::GetInstance()->Clear(); | ||
| 37 | hccpSocketHandle = new int(0); | 38 | hccpSocketHandle = new int(0); |
| 38 | MOCKER_CPP(&SocketHandleManager::Create) | 39 | MOCKER_CPP(&SocketHandleManager::Create) |
| 39 | .stubs() | 40 | .stubs() |
| @@ -51,6 +52,7 @@ protected: | |||
| 51 | 52 | ||
| 52 | virtual void TearDown() | 53 | virtual void TearDown() |
| 53 | { | 54 | { |
| 55 | + PhyTopo::GetInstance()->Clear(); | ||
| 54 | GlobalMockObject::verify(); | 56 | GlobalMockObject::verify(); |
| 55 | delete hccpSocketHandle; | 57 | delete hccpSocketHandle; |
| 56 | std::cout << "A Test case in SocketManagerTest TearDown" << std::endl; | 58 | std::cout << "A Test case in SocketManagerTest TearDown" << std::endl; |
| @@ -178,6 +180,55 @@ TEST_F(SocketManagerTest, Ut_ServerInitAll_Skip_Init_When_Env_Config) | |||
| 178 | EXPECT_NO_THROW(SocketManager::ServerInitAll(rankInfo)); | 180 | EXPECT_NO_THROW(SocketManager::ServerInitAll(rankInfo)); |
| 179 | } | 181 | } |
| 180 | 182 | ||
| 183 | +TEST_F(SocketManagerTest, Ut_ServerInitAll_When_AllRankPortsUnmatched_Expect_NoSocketOrPortChange) | ||
| 184 | +{ | ||
| 185 | + EnvHostNicConfig envConfig; | ||
| 186 | + EnvHostNicConfig& fakeEnvConfig = envConfig; | ||
| 187 | + fakeEnvConfig.hcclDeviceSocketPortRange = CfgField<std::vector<SocketPortRange>>{ | ||
| 188 | + "HCCL_NPU_SOCKET_PORT_RANGE", {{16666, 18888}}, [](const std::string& s) -> std::vector<SocketPortRange> { | ||
| 189 | + return CastSocketPortRange(s, "HCCL_NPU_SOCKET_PORT_RANGE"); | ||
| 190 | + }}; | ||
| 191 | + fakeEnvConfig.hcclDeviceSocketPortRange.isParsed = true; | ||
| 192 | + MOCKER_CPP(&EnvConfig::GetHostNicConfig).stubs().will(returnValue(fakeEnvConfig)); | ||
| 193 | + | ||
| 194 | + string topoFilePath{HCOMM_CODE_ROOT_DIR "/test/legacy/ut/framework/communicator/topo2pclos.json"}; | ||
| 195 | + MOCKER_CPP(&CommunicatorImpl::GetTopoFilePath).stubs().will(returnValue(topoFilePath)); | ||
| 196 | + MOCKER(HrtGetDevice).stubs().will(returnValue(0)); | ||
| 197 | + | ||
| 198 | + RankGraphBuilder rankGraphBuilder; | ||
| 199 | + unique_ptr<RankGraph> graph = rankGraphBuilder.Build(RankTable2pClos, topoFilePath, 0); | ||
| 200 | + ASSERT_NE(nullptr, graph); | ||
| 201 | + NewRankInfo rankInfo = rankGraphBuilder.GetRankTableInfo()->ranks[0]; | ||
| 202 | + auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(); | ||
| 203 | + ASSERT_NE(nullptr, phyTopoGraph); | ||
| 204 | + ASSERT_FALSE(phyTopoGraph->GetEdges(rankInfo.localId).empty()); | ||
| 205 | + rankInfo.devicePort = 31000; | ||
| 206 | + std::vector<u32> expectedSocketPorts; | ||
| 207 | + u32 socketPort = 32000; | ||
| 208 | + for (auto& rankLevelInfo : rankInfo.rankLevelInfos) { | ||
| 209 | + for (auto& rankAddr : rankLevelInfo.rankAddrs) { | ||
| 210 | + rankAddr.ports = {"ut/unmatched/port"}; | ||
| 211 | + rankAddr.socketPort_ = socketPort++; | ||
| 212 | + expectedSocketPorts.push_back(rankAddr.socketPort_); | ||
| 213 | + } | ||
| 214 | + } | ||
| 215 | + auto& serverSocketMap = SocketManager::GetServerSocketMap(); | ||
| 216 | + const auto serverSocketCount = serverSocketMap.size(); | ||
| 217 | + | ||
| 218 | + EXPECT_NO_THROW(SocketManager::ServerInitAll(rankInfo)); | ||
| 219 | + | ||
| 220 | + EXPECT_EQ(serverSocketCount, serverSocketMap.size()); | ||
| 221 | + EXPECT_EQ(31000, rankInfo.devicePort); | ||
| 222 | + size_t addrIndex = 0; | ||
| 223 | + for (const auto& rankLevelInfo : rankInfo.rankLevelInfos) { | ||
| 224 | + for (const auto& rankAddr : rankLevelInfo.rankAddrs) { | ||
| 225 | + ASSERT_LT(addrIndex, expectedSocketPorts.size()); | ||
| 226 | + EXPECT_EQ(expectedSocketPorts[addrIndex++], rankAddr.socketPort_); | ||
| 227 | + } | ||
| 228 | + } | ||
| 229 | + EXPECT_EQ(expectedSocketPorts.size(), addrIndex); | ||
| 230 | +} | ||
| 231 | + | ||
| 181 | TEST_F(SocketManagerTest, test_BatchCreateSockets_with_SocketConfig) | 232 | TEST_F(SocketManagerTest, test_BatchCreateSockets_with_SocketConfig) |
| 182 | { | 233 | { |
| 183 | SocketManager socketMgr(localRank, devicePhyId, devicePhyId, "tmp"); | 234 | SocketManager socketMgr(localRank, devicePhyId, devicePhyId, "tmp"); |
| @@ -292,6 +292,7 @@ const std::string RankTable4p = R"( | |||
| 292 | } | 292 | } |
| 293 | )"; | 293 | )"; |
| 294 | 294 | ||
| 295 | +// Physical topology does not define net_layer; network layers come from the rank table. | ||
| 295 | const std::string Topo1Ser8Dev = R"( | 296 | const std::string Topo1Ser8Dev = R"( |
| 296 | { | 297 | { |
| 297 | "version": "2.0", | 298 | "version": "2.0", |
| @@ -313,7 +314,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 313 | "edge_count": 14, | 314 | "edge_count": 14, |
| 314 | "edge_list": [ | 315 | "edge_list": [ |
| 315 | { | 316 | { |
| 316 | - "net_layer": 0, | ||
| 317 | "link_type": "PEER2PEER", | 317 | "link_type": "PEER2PEER", |
| 318 | "protocols": [ | 318 | "protocols": [ |
| 319 | "UB_CTP" | 319 | "UB_CTP" |
| @@ -329,7 +329,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 329 | "position": "DEVICE" | 329 | "position": "DEVICE" |
| 330 | }, | 330 | }, |
| 331 | { | 331 | { |
| 332 | - "net_layer": 0, | ||
| 333 | "link_type": "PEER2PEER", | 332 | "link_type": "PEER2PEER", |
| 334 | "protocols": [ | 333 | "protocols": [ |
| 335 | "UB_CTP" | 334 | "UB_CTP" |
| @@ -345,7 +344,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 345 | "position": "DEVICE" | 344 | "position": "DEVICE" |
| 346 | }, | 345 | }, |
| 347 | { | 346 | { |
| 348 | - "net_layer": 0, | ||
| 349 | "link_type": "PEER2PEER", | 347 | "link_type": "PEER2PEER", |
| 350 | "protocols": [ | 348 | "protocols": [ |
| 351 | "UB_CTP" | 349 | "UB_CTP" |
| @@ -361,7 +359,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 361 | "position": "DEVICE" | 359 | "position": "DEVICE" |
| 362 | }, | 360 | }, |
| 363 | { | 361 | { |
| 364 | - "net_layer": 0, | ||
| 365 | "link_type": "PEER2PEER", | 362 | "link_type": "PEER2PEER", |
| 366 | "protocols": [ | 363 | "protocols": [ |
| 367 | "UB_CTP" | 364 | "UB_CTP" |
| @@ -377,7 +374,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 377 | "position": "DEVICE" | 374 | "position": "DEVICE" |
| 378 | }, | 375 | }, |
| 379 | { | 376 | { |
| 380 | - "net_layer": 0, | ||
| 381 | "link_type": "PEER2PEER", | 377 | "link_type": "PEER2PEER", |
| 382 | "protocols": [ | 378 | "protocols": [ |
| 383 | "UB_CTP" | 379 | "UB_CTP" |
| @@ -393,7 +389,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 393 | "position": "DEVICE" | 389 | "position": "DEVICE" |
| 394 | }, | 390 | }, |
| 395 | { | 391 | { |
| 396 | - "net_layer": 0, | ||
| 397 | "link_type": "PEER2PEER", | 392 | "link_type": "PEER2PEER", |
| 398 | "protocols": [ | 393 | "protocols": [ |
| 399 | "UB_CTP" | 394 | "UB_CTP" |
| @@ -409,7 +404,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 409 | "position": "DEVICE" | 404 | "position": "DEVICE" |
| 410 | }, | 405 | }, |
| 411 | { | 406 | { |
| 412 | - "net_layer": 1, | ||
| 413 | "link_type": "PEER2NET", | 407 | "link_type": "PEER2NET", |
| 414 | "protocols": [ | 408 | "protocols": [ |
| 415 | "UB_CTP" | 409 | "UB_CTP" |
| @@ -422,7 +416,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 422 | "position": "DEVICE" | 416 | "position": "DEVICE" |
| 423 | }, | 417 | }, |
| 424 | { | 418 | { |
| 425 | - "net_layer": 1, | ||
| 426 | "link_type": "PEER2NET", | 419 | "link_type": "PEER2NET", |
| 427 | "protocols": [ | 420 | "protocols": [ |
| 428 | "UB_CTP" | 421 | "UB_CTP" |
| @@ -435,7 +428,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 435 | "position": "DEVICE" | 428 | "position": "DEVICE" |
| 436 | }, | 429 | }, |
| 437 | { | 430 | { |
| 438 | - "net_layer": 1, | ||
| 439 | "link_type": "PEER2NET", | 431 | "link_type": "PEER2NET", |
| 440 | "protocols": [ | 432 | "protocols": [ |
| 441 | "UB_CTP" | 433 | "UB_CTP" |
| @@ -448,7 +440,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 448 | "position": "DEVICE" | 440 | "position": "DEVICE" |
| 449 | }, | 441 | }, |
| 450 | { | 442 | { |
| 451 | - "net_layer": 1, | ||
| 452 | "link_type": "PEER2NET", | 443 | "link_type": "PEER2NET", |
| 453 | "protocols": [ | 444 | "protocols": [ |
| 454 | "UB_CTP" | 445 | "UB_CTP" |
| @@ -461,7 +452,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 461 | "position": "DEVICE" | 452 | "position": "DEVICE" |
| 462 | }, | 453 | }, |
| 463 | { | 454 | { |
| 464 | - "net_layer": 2, | ||
| 465 | "link_type": "PEER2NET", | 455 | "link_type": "PEER2NET", |
| 466 | "protocols": [ | 456 | "protocols": [ |
| 467 | "UB_CTP" | 457 | "UB_CTP" |
| @@ -474,7 +464,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 474 | "position": "HOST" | 464 | "position": "HOST" |
| 475 | }, | 465 | }, |
| 476 | { | 466 | { |
| 477 | - "net_layer": 2, | ||
| 478 | "link_type": "PEER2NET", | 467 | "link_type": "PEER2NET", |
| 479 | "protocols": [ | 468 | "protocols": [ |
| 480 | "UB_CTP" | 469 | "UB_CTP" |
| @@ -487,7 +476,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 487 | "position": "HOST" | 476 | "position": "HOST" |
| 488 | }, | 477 | }, |
| 489 | { | 478 | { |
| 490 | - "net_layer": 2, | ||
| 491 | "link_type": "PEER2NET", | 479 | "link_type": "PEER2NET", |
| 492 | "protocols": [ | 480 | "protocols": [ |
| 493 | "UB_CTP" | 481 | "UB_CTP" |
| @@ -500,7 +488,6 @@ const std::string Topo1Ser8Dev = R"( | |||
| 500 | "position": "HOST" | 488 | "position": "HOST" |
| 501 | }, | 489 | }, |
| 502 | { | 490 | { |
| 503 | - "net_layer": 2, | ||
| 504 | "link_type": "PEER2NET", | 491 | "link_type": "PEER2NET", |
| 505 | "protocols": [ | 492 | "protocols": [ |
| 506 | "UB_CTP" | 493 | "UB_CTP" |
| @@ -10,6 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | + | ||
| 14 | + | ||
| 13 | 15 | ||
| 14 | 16 | ||
| 15 | 17 | ||
| @@ -415,6 +417,22 @@ int RaGetDevEidInfoList(struct RaInfo info, struct HccpDevEidInfo info_list[], u | |||
| 415 | 417 | ||
| 416 | int RaGetDevBaseAttr(void* ctx_handle, struct DevBaseAttr* attr) { return 0; } | 418 | int RaGetDevBaseAttr(void* ctx_handle, struct DevBaseAttr* attr) { return 0; } |
| 417 | 419 | ||
| 420 | +// legacy UT ??? base_comm ???????? HCCP ???????? | ||
| 421 | +namespace hcomm { | ||
| 422 | + | ||
| 423 | +HcclResult HccpRaGetDevBaseAttr(void* ctxHandle, struct DevBaseAttr* attr) | ||
| 424 | +{ | ||
| 425 | + if (RaGetDevBaseAttr(ctxHandle, attr) != 0) { | ||
| 426 | + return HCCL_E_NETWORK; | ||
| 427 | + } | ||
| 428 | + if (attr != nullptr) { | ||
| 429 | + attr->ub.priorityInfo[0].tpType.bs.ctp = 1; | ||
| 430 | + } | ||
| 431 | + return HCCL_SUCCESS; | ||
| 432 | +} | ||
| 433 | + | ||
| 434 | +} // namespace hcomm | ||
| 435 | + | ||
| 418 | int RaCtxUpdateCi(void* qp_handle, uint16_t ci) { return 0; } | 436 | int RaCtxUpdateCi(void* qp_handle, uint16_t ci) { return 0; } |
| 419 | 437 | ||
| 420 | int RaGetAsyncReqResult(void* req_handle, int* req_result) { return 0; } | 438 | int RaGetAsyncReqResult(void* req_handle, int* req_result) { return 0; } |
| @@ -85,8 +85,8 @@ namespace test { | |||
| 85 | std::initializer_list<std::string> localBPorts = {}, LinkProtocol protocol = LinkProtocol::UB_CTP, | 85 | std::initializer_list<std::string> localBPorts = {}, LinkProtocol protocol = LinkProtocol::UB_CTP, |
| 86 | AddrPosition position = AddrPosition::DEVICE, u32 topoInstId = 0, TopoType topoType = TopoType::CLOS) | 86 | AddrPosition position = AddrPosition::DEVICE, u32 topoInstId = 0, TopoType topoType = TopoType::CLOS) |
| 87 | { | 87 | { |
| 88 | + (void)netLayer; | ||
| 88 | EdgeInfo edge; | 89 | EdgeInfo edge; |
| 89 | - edge.netLayer = netLayer; | ||
| 90 | edge.linkType = linkType; | 90 | edge.linkType = linkType; |
| 91 | edge.topoType = topoType; | 91 | edge.topoType = topoType; |
| 92 | edge.topoInstId = topoInstId; | 92 | edge.topoInstId = topoInstId; |
| @@ -108,9 +108,7 @@ namespace test { | |||
| 108 | topo.peers.emplace_back(MakePeer(localId)); | 108 | topo.peers.emplace_back(MakePeer(localId)); |
| 109 | } | 109 | } |
| 110 | topo.edgeCount = edges.size(); | 110 | topo.edgeCount = edges.size(); |
| 111 | - for (const auto& edge : edges) { | 111 | + topo.edges = edges; |
| 112 | - topo.edges[edge.netLayer].push_back(edge); | ||
| 113 | - } | ||
| 114 | return topo; | 112 | return topo; |
| 115 | } | 113 | } |
| 116 | 114 | ||
| @@ -215,34 +215,26 @@ protected: | |||
| 215 | void TearDown() override {} | 215 | void TearDown() override {} |
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | -TEST_F(PhyTopoTest, Ut_AddTopoGraph_When_TopoNotNullAndNetLayerNotExist_Expect_ReturnTopo) | 218 | +TEST_F(PhyTopoTest, Ut_AddTopoGraph_When_TopoNotNull_Expect_ReturnTopo) |
| 219 | { | 219 | { |
| 220 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | 220 | std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); |
| 221 | - u32 netLayer = 1; | 221 | + phyTopo.AddTopoGraph(topo); |
| 222 | - phyTopo.AddTopoGraph(netLayer, topo); | 222 | + EXPECT_EQ(phyTopo.GetTopoGraph(), topo); |
| 223 | - EXPECT_EQ(phyTopo.GetTopoGraph(netLayer), topo); | ||
| 224 | } | 223 | } |
| 225 | 224 | ||
| 226 | -TEST_F(PhyTopoTest, Ut_GetTopoGraph_When_NetLayerExist_Expect_ReturnTopo) | 225 | +TEST_F(PhyTopoTest, Ut_GetTopoGraph_When_TopoNotAdded_Expect_ReturnNullptr) |
| 227 | { | 226 | { |
| 228 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo1 | 227 | + EXPECT_EQ(phyTopo.GetTopoGraph(), nullptr); |
| 229 | - = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | ||
| 230 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo2 | ||
| 231 | - = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | ||
| 232 | - u32 netLayer1 = 1; | ||
| 233 | - u32 netLayer2 = 2; | ||
| 234 | - phyTopo.AddTopoGraph(netLayer1, topo1); | ||
| 235 | - phyTopo.AddTopoGraph(netLayer2, topo2); | ||
| 236 | - EXPECT_EQ(phyTopo.GetTopoGraph(netLayer1), topo1); | ||
| 237 | - EXPECT_EQ(phyTopo.GetTopoGraph(netLayer2), topo2); | ||
| 238 | } | 228 | } |
| 239 | 229 | ||
| 240 | -TEST_F(PhyTopoTest, Ut_GetTopoGraph_When_NetLayerNoExist_Expect_ReturnNullptr) | 230 | +TEST_F(PhyTopoTest, Ut_Clear_When_TopoAdded_Expect_ResetTopoAndInitFlag) |
| 241 | { | 231 | { |
| 242 | - std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo1 | 232 | + std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> topo = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); |
| 243 | - = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | 233 | + phyTopo.AddTopoGraph(topo); |
| 244 | - u32 netLayer1 = 1; | 234 | + phyTopo.InitFinish(); |
| 245 | - u32 netLayer2 = 2; | 235 | + |
| 246 | - phyTopo.AddTopoGraph(netLayer1, topo1); | 236 | + phyTopo.Clear(); |
| 247 | - EXPECT_EQ(phyTopo.GetTopoGraph(netLayer2), nullptr); | 237 | + |
| 238 | + EXPECT_EQ(phyTopo.GetTopoGraph(), nullptr); | ||
| 239 | + EXPECT_FALSE(phyTopo.IsInitFinished()); | ||
| 248 | } | 240 | } |
| @@ -91,13 +91,9 @@ std::unique_ptr<PhyTopo> PhyTopoBuilderBuildStub(const std::string& topoPath) | |||
| 91 | std::unique_ptr<PhyTopo> phyTopo = std::make_unique<PhyTopo>(); | 91 | std::unique_ptr<PhyTopo> phyTopo = std::make_unique<PhyTopo>(); |
| 92 | PhyTopoBuilder phyTopoBuilder; | 92 | PhyTopoBuilder phyTopoBuilder; |
| 93 | auto topoInfo = phyTopoBuilder.LoadTopoInfo(topoPath); | 93 | auto topoInfo = phyTopoBuilder.LoadTopoInfo(topoPath); |
| 94 | - // 根据topoInfo,按netLayer构造Graph | 94 | + // topoInfo 中的全部物理边构造成一张 Graph。 |
| 95 | - for (const auto& iter : topoInfo->edges) { | 95 | + auto graph = phyTopoBuilder.CreateGraph(topoInfo->edges); |
| 96 | - auto netLayer = iter.first; | 96 | + phyTopo->AddTopoGraph(graph); |
| 97 | - auto graph = phyTopoBuilder.CreateGraph(iter.second); | ||
| 98 | - phyTopo->AddTopoGraph(netLayer, graph); | ||
| 99 | - HCCL_DEBUG("[PhyTopoBuilder::%s]Build netLayer[%u] topo graph success.", __func__, netLayer); | ||
| 100 | - } | ||
| 101 | return phyTopo; | 97 | return phyTopo; |
| 102 | } | 98 | } |
| 103 | 99 | ||
| @@ -117,10 +113,15 @@ protected: | |||
| 117 | 113 | ||
| 118 | static void TearDownTestCase() { std::cout << "PhyTopoBuilderTest TearDown" << std::endl; } | 114 | static void TearDownTestCase() { std::cout << "PhyTopoBuilderTest TearDown" << std::endl; } |
| 119 | 115 | ||
| 120 | - virtual void SetUp() { std::cout << "A Test case in PhyTopoBuilderTest SetUP" << std::endl; } | 116 | + virtual void SetUp() |
| 117 | + { | ||
| 118 | + PhyTopo::GetInstance()->Clear(); | ||
| 119 | + std::cout << "A Test case in PhyTopoBuilderTest SetUP" << std::endl; | ||
| 120 | + } | ||
| 121 | 121 | ||
| 122 | virtual void TearDown() | 122 | virtual void TearDown() |
| 123 | { | 123 | { |
| 124 | + PhyTopo::GetInstance()->Clear(); | ||
| 124 | GlobalMockObject::verify(); | 125 | GlobalMockObject::verify(); |
| 125 | std::cout << "A Test case in PhyTopoBuilderTest TearDown" << std::endl; | 126 | std::cout << "A Test case in PhyTopoBuilderTest TearDown" << std::endl; |
| 126 | } | 127 | } |
| @@ -156,7 +157,7 @@ TEST_F(PhyTopoBuilderTest, Ut_PhyTopoBuilder_When_ValidTopoPath_Expect_ReturnEdg | |||
| 156 | std::string topoPath = "./topo_stub"; | 157 | std::string topoPath = "./topo_stub"; |
| 157 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoStub)); | 158 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoStub)); |
| 158 | std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); | 159 | std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); |
| 159 | - auto graph = phyTopo->GetTopoGraph(0); | 160 | + auto graph = phyTopo->GetTopoGraph(); |
| 160 | size_t totalEdgeNum = 0; | 161 | size_t totalEdgeNum = 0; |
| 161 | 162 | ||
| 162 | // 遍历所有源节点 | 163 | // 遍历所有源节点 |
| @@ -169,24 +170,41 @@ TEST_F(PhyTopoBuilderTest, Ut_PhyTopoBuilder_When_ValidTopoPath_Expect_ReturnEdg | |||
| 169 | } | 170 | } |
| 170 | } | 171 | } |
| 171 | 172 | ||
| 172 | - EXPECT_EQ(totalEdgeNum, 6); | 173 | + EXPECT_EQ(totalEdgeNum, 8); |
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | -TEST_F(PhyTopoBuilderTest, Ut_PhyTopoBuilder_When_EdgeRepeat_Expect_ReturnEdgeNum) | 176 | +TEST_F(PhyTopoBuilderTest, Ut_PhyTopoBuilder_When_EdgeRepeat_Expect_KeepInputEdges) |
| 176 | { | 177 | { |
| 177 | std::string topoPath = "./test_topo_stub"; | 178 | std::string topoPath = "./test_topo_stub"; |
| 178 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoWithRepeatEdge)); | 179 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoWithRepeatEdge)); |
| 179 | - std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); | 180 | + std::unique_ptr<PhyTopo> phyTopo; |
| 180 | - auto graph = phyTopo->GetTopoGraph(0); | 181 | + EXPECT_NO_THROW(phyTopo = PhyTopoBuilderBuildStub(topoPath)); |
| 182 | + ASSERT_NE(phyTopo, nullptr); | ||
| 183 | + auto graph = phyTopo->GetTopoGraph(); | ||
| 181 | ASSERT_NE(graph, nullptr); | 184 | ASSERT_NE(graph, nullptr); |
| 185 | + // TopoInfo 解析阶段负责去重;建图阶段按输入边构建双向物理边。 | ||
| 186 | + EXPECT_EQ(graph->GetEdges(PhyTopo::Peer::GetId(0), PhyTopo::Peer::GetId(1)).size(), 2); | ||
| 187 | + EXPECT_EQ(graph->GetEdges(PhyTopo::Peer::GetId(1), PhyTopo::Peer::GetId(0)).size(), 2); | ||
| 188 | +} | ||
| 182 | 189 | ||
| 183 | - size_t totalEdgeNum = 0; | 190 | +TEST_F(PhyTopoBuilderTest, Ut_BuildPhyTopo_When_NoEdges_Expect_KeepIsolatedPeers) |
| 184 | - for (const auto& srcEntry : graph->edges) { | 191 | +{ |
| 185 | - for (const auto& dstEntry : srcEntry.second) { | 192 | + TopoInfo topoInfo; |
| 186 | - totalEdgeNum += dstEntry.second.size(); | 193 | + topoInfo.version = "2.0"; |
| 187 | - } | 194 | + topoInfo.peerCount = 3; |
| 195 | + for (u32 localId = 0; localId < topoInfo.peerCount; ++localId) { | ||
| 196 | + PeerInfo peer; | ||
| 197 | + peer.localId = localId; | ||
| 198 | + topoInfo.peers.emplace_back(peer); | ||
| 188 | } | 199 | } |
| 189 | - EXPECT_EQ(totalEdgeNum, 4); | 200 | + |
| 201 | + PhyTopoBuilder phyTopoBuilder; | ||
| 202 | + phyTopoBuilder.BuildPhyTopo(topoInfo); | ||
| 203 | + | ||
| 204 | + auto graph = PhyTopo::GetInstance()->GetTopoGraph(); | ||
| 205 | + ASSERT_NE(graph, nullptr); | ||
| 206 | + EXPECT_EQ(graph->nodes.size(), 3); | ||
| 207 | + EXPECT_TRUE(graph->edges.empty()); | ||
| 190 | } | 208 | } |
| 191 | 209 | ||
| 192 | TEST_F(PhyTopoBuilderTest, Ut_PhyTopoBuilder_When_DiffProtocols_Expect_ReturnEdgeNum) | 210 | TEST_F(PhyTopoBuilderTest, Ut_PhyTopoBuilder_When_DiffProtocols_Expect_ReturnEdgeNum) |
| @@ -194,7 +212,7 @@ TEST_F(PhyTopoBuilderTest, Ut_PhyTopoBuilder_When_DiffProtocols_Expect_ReturnEdg | |||
| 194 | std::string topoPath = "./topo_stub"; | 212 | std::string topoPath = "./topo_stub"; |
| 195 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoWithDiffProtocols)); | 213 | MOCKER_CPP(&PhyTopoBuilder::LoadTopoInfo).stubs().will(invoke(LoadTopoInfoWithDiffProtocols)); |
| 196 | std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); | 214 | std::unique_ptr<PhyTopo> phyTopo = PhyTopoBuilderBuildStub(topoPath); |
| 197 | - auto graph = phyTopo->GetTopoGraph(0); | 215 | + auto graph = phyTopo->GetTopoGraph(); |
| 198 | size_t totalEdgeNum = 0; | 216 | size_t totalEdgeNum = 0; |
| 199 | 217 | ||
| 200 | // 遍历所有源节点 | 218 | // 遍历所有源节点 |
| @@ -526,6 +526,79 @@ TEST_F(RankGraphTest, ut_GetEndpointDesc_When_Normal_Expect_SUCCESS) | |||
| 526 | EXPECT_EQ(ret, HCCL_SUCCESS); | 526 | EXPECT_EQ(ret, HCCL_SUCCESS); |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | +TEST_F(RankGraphTest, ut_GetEndpointInfo_When_SameEndpointAcrossLayers_Expect_LayerSpecificBwCoeff) | ||
| 530 | +{ | ||
| 531 | + constexpr u32 topoInstId = 0; | ||
| 532 | + constexpr u32 layer1 = 1; | ||
| 533 | + constexpr u32 layer2 = 2; | ||
| 534 | + RankGraph rankGraph(myRank); | ||
| 535 | + auto peer = createPeer(myRank); | ||
| 536 | + rankGraph.AddPeer(peer); | ||
| 537 | + | ||
| 538 | + IpAddress endpointAddr("192.168.1.1"); | ||
| 539 | + CommAddr commAddr{}; | ||
| 540 | + commAddr.type = COMM_ADDR_TYPE_IP_V4; | ||
| 541 | + commAddr.addr = endpointAddr.GetBinaryAddress().addr; | ||
| 542 | + std::set<LinkProtocol> protocols = {LinkProtocol::UB_CTP}; | ||
| 543 | + auto layer1Iface = std::make_shared<NetInstance::ConnInterface>( | ||
| 544 | + endpointAddr, std::set<std::string>{"1/0"}, AddrPosition::DEVICE, LinkType::PEER2NET, protocols, TopoType::CLOS, | ||
| 545 | + topoInstId); | ||
| 546 | + auto layer2Iface = std::make_shared<NetInstance::ConnInterface>( | ||
| 547 | + endpointAddr, std::set<std::string>{"2/0", "2/1"}, AddrPosition::DEVICE, LinkType::PEER2NET, protocols, | ||
| 548 | + TopoType::CLOS, topoInstId); | ||
| 549 | + peer->AddConnInterface(layer1, layer1Iface); | ||
| 550 | + peer->AddConnInterface(layer2, layer2Iface); | ||
| 551 | + peer->SetEndpointToIface(layer1, topoInstId, commAddr, COMM_PROTOCOL_UBC_CTP, layer1Iface); | ||
| 552 | + peer->SetEndpointToIface(layer2, topoInstId, commAddr, COMM_PROTOCOL_UBC_CTP, layer2Iface); | ||
| 553 | + | ||
| 554 | + EndpointDesc layer1Desc; | ||
| 555 | + EndpointDesc layer2Desc; | ||
| 556 | + uint32_t descNum = 1; | ||
| 557 | + ASSERT_EQ(rankGraph.GetEndpointDesc(layer1, topoInstId, &descNum, &layer1Desc), HCCL_SUCCESS); | ||
| 558 | + ASSERT_EQ(descNum, 1); | ||
| 559 | + u32 descNetLayer = UINT32_MAX; | ||
| 560 | + u32 descTopoInstId = UINT32_MAX; | ||
| 561 | + ASSERT_TRUE(GetEndpointTopoInfo(layer1Desc, descNetLayer, descTopoInstId)); | ||
| 562 | + EXPECT_EQ(descNetLayer, layer1); | ||
| 563 | + EXPECT_EQ(descTopoInstId, topoInstId); | ||
| 564 | + descNum = 1; | ||
| 565 | + ASSERT_EQ(rankGraph.GetEndpointDesc(layer2, topoInstId, &descNum, &layer2Desc), HCCL_SUCCESS); | ||
| 566 | + ASSERT_EQ(descNum, 1); | ||
| 567 | + ASSERT_TRUE(GetEndpointTopoInfo(layer2Desc, descNetLayer, descTopoInstId)); | ||
| 568 | + EXPECT_EQ(descNetLayer, layer2); | ||
| 569 | + EXPECT_EQ(descTopoInstId, topoInstId); | ||
| 570 | + | ||
| 571 | + EndpointDesc copiedLayer2Desc; | ||
| 572 | + ASSERT_EQ(EndpointDescInit(&copiedLayer2Desc, 1), HCCL_SUCCESS); | ||
| 573 | + copiedLayer2Desc.protocol = layer2Desc.protocol; | ||
| 574 | + copiedLayer2Desc.commAddr = layer2Desc.commAddr; | ||
| 575 | + copiedLayer2Desc.loc = layer2Desc.loc; | ||
| 576 | + ASSERT_TRUE(GetEndpointTopoInfo(copiedLayer2Desc, descNetLayer, descTopoInstId)); | ||
| 577 | + EXPECT_EQ(descNetLayer, layer2); | ||
| 578 | + EXPECT_EQ(descTopoInstId, topoInstId); | ||
| 579 | + | ||
| 580 | + EndpointAttrBwCoeff layer1BwCoeff = 0; | ||
| 581 | + EndpointAttrBwCoeff layer2BwCoeff = 0; | ||
| 582 | + EXPECT_EQ( | ||
| 583 | + rankGraph.GetEndpointInfo(myRank, &layer1Desc, ENDPOINT_ATTR_BW_COEFF, sizeof(layer1BwCoeff), &layer1BwCoeff), | ||
| 584 | + HCCL_SUCCESS); | ||
| 585 | + EXPECT_EQ( | ||
| 586 | + rankGraph.GetEndpointInfo( | ||
| 587 | + myRank, &copiedLayer2Desc, ENDPOINT_ATTR_BW_COEFF, sizeof(layer2BwCoeff), &layer2BwCoeff), | ||
| 588 | + HCCL_SUCCESS); | ||
| 589 | + EXPECT_EQ(layer1BwCoeff, 1); | ||
| 590 | + EXPECT_EQ(layer2BwCoeff, 2); | ||
| 591 | + | ||
| 592 | + EndpointDesc legacyDesc; | ||
| 593 | + ASSERT_EQ(EndpointDescInit(&legacyDesc, 1), HCCL_SUCCESS); | ||
| 594 | + legacyDesc.commAddr = layer1Desc.commAddr; | ||
| 595 | + legacyDesc.protocol = layer1Desc.protocol; | ||
| 596 | + legacyDesc.loc.locType = layer1Desc.loc.locType; | ||
| 597 | + EXPECT_EQ( | ||
| 598 | + rankGraph.GetEndpointInfo(myRank, &legacyDesc, ENDPOINT_ATTR_BW_COEFF, sizeof(layer1BwCoeff), &layer1BwCoeff), | ||
| 599 | + HCCL_E_PARA); | ||
| 600 | +} | ||
| 601 | + | ||
| 529 | TEST_F(RankGraphTest, ut_AddGroupLinks_When_1pNormal_Expect_SUCCESS) | 602 | TEST_F(RankGraphTest, ut_AddGroupLinks_When_1pNormal_Expect_SUCCESS) |
| 530 | { | 603 | { |
| 531 | auto rankGraph = create4pRankGraph(myRank); | 604 | auto rankGraph = create4pRankGraph(myRank); |
| @@ -51,6 +51,52 @@ protected: | |||
| 51 | } | 51 | } |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | +TEST_F(RankGraph64Plus1Test, Ut_GetPeer2PlaneEdges_When_MultiPortNoiseNotInLayer0_Expect_Ignored) | ||
| 55 | +{ | ||
| 56 | + auto phyTopoGraph = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | ||
| 57 | + auto phyPeer = std::make_shared<PhyTopo::Peer>(64); | ||
| 58 | + auto phyFabric = std::make_shared<PhyTopo::Fabric>(); | ||
| 59 | + const NodeId peerNodeId = PhyTopo::Peer::GetId(64); | ||
| 60 | + const NodeId fabricNodeId = PhyTopo::Fabric::GetId(); | ||
| 61 | + phyTopoGraph->AddNode(peerNodeId, phyPeer); | ||
| 62 | + phyTopoGraph->AddNode(fabricNodeId, phyFabric); | ||
| 63 | + | ||
| 64 | + auto rankPeer = std::make_shared<NetInstance::Peer>(0, 64, 64, 0); | ||
| 65 | + const std::vector<std::set<std::string>> physicalPlanePortGroups = { | ||
| 66 | + {"0/0", "0/1", "0/2", "0/3"}, | ||
| 67 | + {"0/4", "0/5", "0/6", "0/7"}, | ||
| 68 | + {"1/0", "1/1", "1/2", "1/3"}, | ||
| 69 | + {"1/4", "1/5", "1/6", "1/7"}, | ||
| 70 | + }; | ||
| 71 | + std::map<std::string, std::vector<IpAddress>> layer0PortAddrMap; | ||
| 72 | + layer0PortAddrMap["1/0"] = {IpAddress("192.168.0.1")}; | ||
| 73 | + rankPeer->SetPortPortAddrMapLayer0(layer0PortAddrMap); | ||
| 74 | + | ||
| 75 | + PhyTopo::LinkAttributes linkAttrs; | ||
| 76 | + linkAttrs.linktype = LinkType::PEER2NET; | ||
| 77 | + linkAttrs.protocols = {LinkProtocol::UB_CTP}; | ||
| 78 | + for (u32 planeId = 0; planeId < static_cast<u32>(physicalPlanePortGroups.size()); ++planeId) { | ||
| 79 | + auto edge = std::make_shared<PhyTopo::Link>(phyPeer, phyFabric, linkAttrs, TopoType::CLOS, planeId); | ||
| 80 | + edge->SetSourceIface(std::make_shared<PhyTopo::ConnInterface>( | ||
| 81 | + physicalPlanePortGroups[planeId], AddrPosition::DEVICE, LinkType::PEER2NET, linkAttrs.protocols)); | ||
| 82 | + phyTopoGraph->AddEdge(peerNodeId, fabricNodeId, edge); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + auto noiseEdge = std::make_shared<PhyTopo::Link>(phyPeer, phyFabric, linkAttrs, TopoType::CLOS, 2); | ||
| 86 | + noiseEdge->SetSourceIface(std::make_shared<PhyTopo::ConnInterface>( | ||
| 87 | + std::set<std::string>{"9/0", "9/1", "9/2", "9/3"}, AddrPosition::DEVICE, LinkType::PEER2NET, | ||
| 88 | + linkAttrs.protocols)); | ||
| 89 | + phyTopoGraph->AddEdge(peerNodeId, fabricNodeId, noiseEdge); | ||
| 90 | + | ||
| 91 | + UpdaterFor64Plus1 updater; | ||
| 92 | + std::shared_ptr<PhyTopo::Link> matchedEdge; | ||
| 93 | + EXPECT_NO_THROW( | ||
| 94 | + matchedEdge | ||
| 95 | + = updater.GetPeer2PlaneEdges(2, rankPeer, phyTopoGraph, BACKUP_TO_PLANE_ADDR_NUM, linkAttrs.protocols)); | ||
| 96 | + ASSERT_NE(matchedEdge, nullptr); | ||
| 97 | + EXPECT_EQ(matchedEdge->GetTopoInstId(), 2); | ||
| 98 | +} | ||
| 99 | + | ||
| 54 | TEST_F(RankGraph64Plus1Test, test_4p_without_backup) | 100 | TEST_F(RankGraph64Plus1Test, test_4p_without_backup) |
| 55 | { | 101 | { |
| 56 | // ranktable不使用备份, topo文件也无备份信息 | 102 | // ranktable不使用备份, topo文件也无备份信息 |
| @@ -116,14 +162,24 @@ TEST_F(RankGraph64Plus1Test, test_RankGraph_Build_without_Backup) | |||
| 116 | EXPECT_EQ(rankGraph->peers_[i]->GetNodeId(), i); | 162 | EXPECT_EQ(rankGraph->peers_[i]->GetNodeId(), i); |
| 117 | EXPECT_EQ(rankGraph->peers_[i]->GetLevels().size(), 2); | 163 | EXPECT_EQ(rankGraph->peers_[i]->GetLevels().size(), 2); |
| 118 | } | 164 | } |
| 165 | + // topo 中 net_layer=99 的 0/9 噪声端口不能污染 rankTable 定义的 layer 0 接口 | ||
| 166 | + for (const auto& rankPeer : rankGraph->peers_) { | ||
| 167 | + const auto layer0Ifaces = rankPeer.second->GetIfacesByLayer(0); | ||
| 168 | + EXPECT_FALSE(layer0Ifaces.empty()); | ||
| 169 | + for (const auto& iface : layer0Ifaces) { | ||
| 170 | + ASSERT_NE(nullptr, iface); | ||
| 171 | + EXPECT_EQ(0, iface->GetPorts().count("0/9")); | ||
| 172 | + } | ||
| 173 | + } | ||
| 119 | // check fabGroups | 174 | // check fabGroups |
| 120 | // check level0 az0-rack0 | 175 | // check level0 az0-rack0 |
| 121 | NetInstance* netInstL0 = rankGraph->GetNetInstanceByNetInstId(0, "az0-rack0"); | 176 | NetInstance* netInstL0 = rankGraph->GetNetInstanceByNetInstId(0, "az0-rack0"); |
| 122 | EXPECT_NE(netInstL0, nullptr); | 177 | EXPECT_NE(netInstL0, nullptr); |
| 123 | EXPECT_EQ(netInstL0->rankIds, expectRanks); | 178 | EXPECT_EQ(netInstL0->rankIds, expectRanks); |
| 124 | EXPECT_EQ(netInstL0->peers.size(), 4); | 179 | EXPECT_EQ(netInstL0->peers.size(), 4); |
| 125 | - EXPECT_EQ(netInstL0->fabrics.size(), 4); | 180 | + ASSERT_EQ(netInstL0->fabrics.size(), 1); |
| 126 | - EXPECT_EQ(netInstL0->vGraph.nodes.size(), 8); | 181 | + EXPECT_EQ(netInstL0->vGraph.nodes.size(), 5); |
| 182 | + EXPECT_EQ(netInstL0->fabrics[0]->GetPlaneId(), "0"); | ||
| 127 | 183 | ||
| 128 | for (u32 i = 1; i < expectRanks.size() - 1; i++) { | 184 | for (u32 i = 1; i < expectRanks.size() - 1; i++) { |
| 129 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->source_->GetNodeId(), 0); | 185 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->source_->GetNodeId(), 0); |
| @@ -168,8 +224,8 @@ TEST_F(RankGraph64Plus1Test, test_RankGraph_Build_with_Backup) | |||
| 168 | EXPECT_NE(netInstL0, nullptr); | 224 | EXPECT_NE(netInstL0, nullptr); |
| 169 | EXPECT_EQ(netInstL0->rankIds, expectRanks); | 225 | EXPECT_EQ(netInstL0->rankIds, expectRanks); |
| 170 | EXPECT_EQ(netInstL0->peers.size(), 4); | 226 | EXPECT_EQ(netInstL0->peers.size(), 4); |
| 171 | - EXPECT_EQ(netInstL0->fabrics.size(), 4); // netLayer0支持peer2net的边rankGraph会有4个fabric | 227 | + EXPECT_EQ(netInstL0->fabrics.size(), 1); // rankTable未配置plane_id,所有地址归入默认plane 0 |
| 172 | - EXPECT_EQ(netInstL0->vGraph.nodes.size(), 8); | 228 | + EXPECT_EQ(netInstL0->vGraph.nodes.size(), 5); |
| 173 | for (u32 i = 1; i < expectRanks.size() - 1; i++) { | 229 | for (u32 i = 1; i < expectRanks.size() - 1; i++) { |
| 174 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->source_->GetNodeId(), 0); | 230 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->source_->GetNodeId(), 0); |
| 175 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->target_->GetNodeId(), i); | 231 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->target_->GetNodeId(), i); |
| @@ -214,8 +270,8 @@ TEST_F(RankGraph64Plus1Test, test_checkpoint_normal_to_backup) | |||
| 214 | EXPECT_NE(netInstL0, nullptr); | 270 | EXPECT_NE(netInstL0, nullptr); |
| 215 | EXPECT_EQ(netInstL0->rankIds, expectRanks); | 271 | EXPECT_EQ(netInstL0->rankIds, expectRanks); |
| 216 | EXPECT_EQ(netInstL0->peers.size(), 4); | 272 | EXPECT_EQ(netInstL0->peers.size(), 4); |
| 217 | - EXPECT_EQ(netInstL0->fabrics.size(), 4); | 273 | + EXPECT_EQ(netInstL0->fabrics.size(), 1); |
| 218 | - EXPECT_EQ(netInstL0->vGraph.nodes.size(), 8); | 274 | + EXPECT_EQ(netInstL0->vGraph.nodes.size(), 5); |
| 219 | for (u32 i = 1; i < expectRanks.size() - 1; i++) { | 275 | for (u32 i = 1; i < expectRanks.size() - 1; i++) { |
| 220 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->source_->GetNodeId(), 0); | 276 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->source_->GetNodeId(), 0); |
| 221 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->target_->GetNodeId(), i); | 277 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->target_->GetNodeId(), i); |
| @@ -259,8 +315,8 @@ TEST_F(RankGraph64Plus1Test, test_checkpoint_normal_switch_pod_without_backup) | |||
| 259 | EXPECT_NE(netInstL0, nullptr); | 315 | EXPECT_NE(netInstL0, nullptr); |
| 260 | EXPECT_EQ(netInstL0->rankIds, expectRanks); | 316 | EXPECT_EQ(netInstL0->rankIds, expectRanks); |
| 261 | EXPECT_EQ(netInstL0->peers.size(), 4); | 317 | EXPECT_EQ(netInstL0->peers.size(), 4); |
| 262 | - EXPECT_EQ(netInstL0->fabrics.size(), 4); | 318 | + EXPECT_EQ(netInstL0->fabrics.size(), 1); |
| 263 | - EXPECT_EQ(netInstL0->vGraph.nodes.size(), 8); | 319 | + EXPECT_EQ(netInstL0->vGraph.nodes.size(), 5); |
| 264 | for (u32 i = 1; i < expectRanks.size() - 1; i++) { | 320 | for (u32 i = 1; i < expectRanks.size() - 1; i++) { |
| 265 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->source_->GetNodeId(), 0); | 321 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->source_->GetNodeId(), 0); |
| 266 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->target_->GetNodeId(), i); | 322 | EXPECT_EQ(netInstL0->vGraph.edges[0][i][0]->target_->GetNodeId(), i); |
| @@ -9,15 +9,32 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 12 | 21 | ||
| 13 | 22 | ||
| 14 | -#include <iostream> | 23 | + |
| 15 | -#include <unistd.h> | 24 | +#include <hccl/hccl_types.h> |
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +namespace hcomm { | ||
| 30 | +HcclResult HccpRaGetDevBaseAttr(void* ctxHandle, struct DevBaseAttr* attr); | ||
| 31 | +} | ||
| 16 | 32 | ||
| 17 | 33 | ||
| 18 | 34 | ||
| 19 | 35 | ||
| 20 | 36 | ||
| 37 | + | ||
| 21 | 38 | ||
| 22 | 39 | ||
| 23 | 40 | ||
| @@ -29,6 +46,130 @@ | |||
| 29 | 46 | ||
| 30 | using namespace Hccl; | 47 | using namespace Hccl; |
| 31 | 48 | ||
| 49 | +namespace { | ||
| 50 | +AddressInfo MakeEidAddress(const std::string& eid, std::initializer_list<std::string> ports, const std::string& planeId) | ||
| 51 | +{ | ||
| 52 | + AddressInfo address; | ||
| 53 | + address.addr = IpAddress(IpAddress::StrToEID(eid)); | ||
| 54 | + address.addrType = AddrType::EID; | ||
| 55 | + address.ports = std::set<std::string>(ports.begin(), ports.end()); | ||
| 56 | + address.planeId = planeId; | ||
| 57 | + return address; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +std::vector<AddressInfo> MakeOverlappedUbAddresses(u32 rankId, LinkProtocol protocol) | ||
| 61 | +{ | ||
| 62 | + const std::string eid0 = rankId == 0U ? "00000000000000000000000000000001" : "00000000000000000000000000000011"; | ||
| 63 | + const std::string eid1 = rankId == 0U ? "00000000000000000000000000000002" : "00000000000000000000000000000012"; | ||
| 64 | + if (protocol == LinkProtocol::UB_CTP) { | ||
| 65 | + return { | ||
| 66 | + MakeEidAddress(eid0, {"0/0", "0/1", "0/2", "0/3", "0/4", "0/5"}, "planeA"), | ||
| 67 | + MakeEidAddress(eid1, {"0/6", "0/7"}, "planeB"), | ||
| 68 | + }; | ||
| 69 | + } | ||
| 70 | + return { | ||
| 71 | + MakeEidAddress(eid0, {"0/0", "0/1"}, "planeA"), | ||
| 72 | + MakeEidAddress(eid1, {"0/6", "0/7"}, "planeB"), | ||
| 73 | + }; | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +RankTableInfo MakeOverlappedUbRankTable(u32 netLayer, LinkProtocol protocol) | ||
| 77 | +{ | ||
| 78 | + return test::MakeRankTable({ | ||
| 79 | + test::MakeRankInfo( | ||
| 80 | + 0, 0, 0, | ||
| 81 | + { | ||
| 82 | + test::MakeRankLevel( | ||
| 83 | + 0, "inner", NetType::TOPO_FILE_DESC, | ||
| 84 | + { | ||
| 85 | + test::MakeAddress("192.168.0.1", {"1/0"}), | ||
| 86 | + }), | ||
| 87 | + test::MakeRankLevel(netLayer, "all", NetType::CLOS, MakeOverlappedUbAddresses(0, protocol)), | ||
| 88 | + }), | ||
| 89 | + test::MakeRankInfo( | ||
| 90 | + 1, 1, 1, | ||
| 91 | + { | ||
| 92 | + test::MakeRankLevel( | ||
| 93 | + 0, "inner", NetType::TOPO_FILE_DESC, | ||
| 94 | + { | ||
| 95 | + test::MakeAddress("192.168.0.2", {"1/1"}), | ||
| 96 | + }), | ||
| 97 | + test::MakeRankLevel(netLayer, "all", NetType::CLOS, MakeOverlappedUbAddresses(1, protocol)), | ||
| 98 | + }), | ||
| 99 | + }); | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +RankTableInfo MakeOverlappedUbRankTableForLayer1And2() | ||
| 103 | +{ | ||
| 104 | + RankTableInfo rankTable = MakeOverlappedUbRankTable(1, LinkProtocol::UB_CTP); | ||
| 105 | + for (auto& rankInfo : rankTable.ranks) { | ||
| 106 | + rankInfo.rankLevelInfos.emplace_back(test::MakeRankLevel( | ||
| 107 | + 2, "all-layer2", NetType::CLOS, MakeOverlappedUbAddresses(rankInfo.rankId, LinkProtocol::UB_CTP))); | ||
| 108 | + } | ||
| 109 | + return rankTable; | ||
| 110 | +} | ||
| 111 | + | ||
| 112 | +TopoInfo MakeOverlappedUbTopo(bool addLocalTpEdge = true, bool addDuplicateCtpEdge = false) | ||
| 113 | +{ | ||
| 114 | + std::vector<EdgeInfo> edges = { | ||
| 115 | + test::MakeEdge(0, LinkType::PEER2PEER, 0, {"1/0"}, 1, {"1/1"}), | ||
| 116 | + }; | ||
| 117 | + for (u32 localId = 0U; localId < 2U; ++localId) { | ||
| 118 | + EdgeInfo ctpEdge | ||
| 119 | + = test::MakeEdge(0, LinkType::PEER2NET, localId, {"0/0", "0/1", "0/2", "0/3", "0/4", "0/5", "0/6", "0/7"}); | ||
| 120 | + ctpEdge.protocols = {LinkProtocol::UB_CTP, LinkProtocol::UB_MEM}; | ||
| 121 | + if (addDuplicateCtpEdge) { | ||
| 122 | + EdgeInfo duplicateCtpEdge = ctpEdge; | ||
| 123 | + duplicateCtpEdge.topoInstId = 8; | ||
| 124 | + edges.emplace_back(std::move(duplicateCtpEdge)); | ||
| 125 | + } | ||
| 126 | + edges.emplace_back(std::move(ctpEdge)); | ||
| 127 | + if (addLocalTpEdge || localId != 0U) { | ||
| 128 | + edges.emplace_back(test::MakeEdge( | ||
| 129 | + 0, LinkType::PEER2NET, localId, {"0/0", "0/1", "0/6", "0/7"}, 0, {}, LinkProtocol::UB_TP)); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + return test::MakeTopoInfo({0, 1}, edges); | ||
| 133 | +} | ||
| 134 | + | ||
| 135 | +void MockDevBaseAttr(DevBaseAttr* devBaseAttr, u32 callCount = 2U) | ||
| 136 | +{ | ||
| 137 | + MOCKER_CPP(&RdmaHandleManager::GetByIp).stubs().will(returnValue(static_cast<RdmaHandle>(devBaseAttr))); | ||
| 138 | + MOCKER(hcomm::HccpRaGetDevBaseAttr) | ||
| 139 | + .expects(exactly(callCount)) | ||
| 140 | + .with(mockcpp::any(), outBoundP(devBaseAttr, sizeof(*devBaseAttr))) | ||
| 141 | + .will(returnValue(HCCL_SUCCESS)); | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +void CheckOverlappedUbPaths( | ||
| 145 | + const RankGraph& rankGraph, u32 netLayer, const std::set<LinkProtocol>& expectedProtocols, | ||
| 146 | + const std::multiset<size_t>& expectedPortCounts) | ||
| 147 | +{ | ||
| 148 | + const std::vector<NetInstance::Path> paths = rankGraph.GetPaths(netLayer, 0, 1); | ||
| 149 | + ASSERT_EQ(2, paths.size()); | ||
| 150 | + std::multiset<size_t> portCounts; | ||
| 151 | + for (const auto& path : paths) { | ||
| 152 | + ASSERT_EQ(2, path.links.size()); | ||
| 153 | + EXPECT_EQ(expectedProtocols, path.links[0].GetLinkProtocols()); | ||
| 154 | + EXPECT_EQ(expectedProtocols, path.links[1].GetLinkProtocols()); | ||
| 155 | + ASSERT_NE(nullptr, path.links[0].GetSourceIface()); | ||
| 156 | + portCounts.emplace(path.links[0].GetSourceIface()->GetPorts().size()); | ||
| 157 | + } | ||
| 158 | + EXPECT_EQ(expectedPortCounts, portCounts); | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +void CheckSingleTopoInst(const RankGraph& rankGraph, u32 netLayer) | ||
| 162 | +{ | ||
| 163 | + const NetInstance* netInst = rankGraph.GetNetInstanceByRankId(netLayer, 0); | ||
| 164 | + ASSERT_NE(nullptr, netInst); | ||
| 165 | + std::vector<u32> topoInstIds; | ||
| 166 | + u32 topoInstNum = 0U; | ||
| 167 | + netInst->GetTopoInstsByLayer(topoInstIds, topoInstNum); | ||
| 168 | + EXPECT_EQ(1U, topoInstNum); | ||
| 169 | + EXPECT_EQ((std::vector<u32>{0U}), topoInstIds); | ||
| 170 | +} | ||
| 171 | +} // namespace | ||
| 172 | + | ||
| 32 | class RankGraphBuilderTest : public testing::Test { | 173 | class RankGraphBuilderTest : public testing::Test { |
| 33 | protected: | 174 | protected: |
| 34 | static void SetUpTestCase() { std::cout << "RankGraphBuilderTest SetUP" << std::endl; } | 175 | static void SetUpTestCase() { std::cout << "RankGraphBuilderTest SetUP" << std::endl; } |
| @@ -105,7 +246,7 @@ TEST_F(RankGraphBuilderTest, Ut_Build_When_OnePTopoFileWithoutEdge_Expect_Succes | |||
| 105 | PhyTopo::GetInstance()->Clear(); | 246 | PhyTopo::GetInstance()->Clear(); |
| 106 | auto graph = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); | 247 | auto graph = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>(); |
| 107 | graph->AddNode(PhyTopo::Peer::GetId(0), std::make_shared<PhyTopo::Peer>(0)); | 248 | graph->AddNode(PhyTopo::Peer::GetId(0), std::make_shared<PhyTopo::Peer>(0)); |
| 108 | - PhyTopo::GetInstance()->AddTopoGraph(0, graph); | 249 | + PhyTopo::GetInstance()->AddTopoGraph(graph); |
| 109 | PhyTopo::GetInstance()->InitFinish(); | 250 | PhyTopo::GetInstance()->InitFinish(); |
| 110 | RankGraphBuilder rankGraphBuilder; | 251 | RankGraphBuilder rankGraphBuilder; |
| 111 | std::unique_ptr<RankGraph> rankGraph | 252 | std::unique_ptr<RankGraph> rankGraph |
| @@ -118,14 +259,17 @@ TEST_F(RankGraphBuilderTest, Ut_Build_When_OnePTopoFileWithoutEdge_Expect_Succes | |||
| 118 | EXPECT_EQ(peer->GetLocalId(), 0); | 259 | EXPECT_EQ(peer->GetLocalId(), 0); |
| 119 | } | 260 | } |
| 120 | 261 | ||
| 121 | -TEST_F(RankGraphBuilderTest, Ut_BuildFromRankTable_When_NetLayerInconsistent_Expect_InvalidParamsException) | 262 | +TEST_F(RankGraphBuilderTest, Ut_BuildFromRankTable_When_NetLayerMissingInTopo_Expect_Success) |
| 122 | { | 263 | { |
| 123 | // 校验BuildFromRankTable的Add(RankId, Peer) | 264 | // 校验BuildFromRankTable的Add(RankId, Peer) |
| 124 | // when | 265 | // when |
| 125 | MOCKER_CPP(&PhyTopoBuilder::Build).stubs().with(mockcpp::any()).will(ignoreReturnValue()); | 266 | MOCKER_CPP(&PhyTopoBuilder::Build).stubs().with(mockcpp::any()).will(ignoreReturnValue()); |
| 267 | + // 本用例只验证 RankTable 建图,不依赖物理拓扑构建。 | ||
| 268 | + MOCKER_CPP(&RankGraphBuilder::AddTopoDescFabricInfo).stubs().will(ignoreReturnValue()); | ||
| 126 | MOCKER_CPP(&RankGraph::InitInnerRanks).stubs().will(ignoreReturnValue()); | 269 | MOCKER_CPP(&RankGraph::InitInnerRanks).stubs().will(ignoreReturnValue()); |
| 127 | MOCKER_CPP(&DetourService::InsertDetourLinks).stubs().with(mockcpp::any()).will(ignoreReturnValue()); | 270 | MOCKER_CPP(&DetourService::InsertDetourLinks).stubs().with(mockcpp::any()).will(ignoreReturnValue()); |
| 128 | MOCKER_CPP(&RankGraphBuilder::BuildPeer2PeerLinks).stubs().will(ignoreReturnValue()); | 271 | MOCKER_CPP(&RankGraphBuilder::BuildPeer2PeerLinks).stubs().will(ignoreReturnValue()); |
| 272 | + MOCKER_CPP(&RankGraphBuilder::UpdateTopoInstForMyRankOnly).stubs().will(ignoreReturnValue()); | ||
| 129 | MOCKER_CPP(&RankGraphBuilder::AddFabricInfo).stubs().will(ignoreReturnValue()); | 273 | MOCKER_CPP(&RankGraphBuilder::AddFabricInfo).stubs().will(ignoreReturnValue()); |
| 130 | // then | 274 | // then |
| 131 | RankGraphBuilder rankGraphBuilder; | 275 | RankGraphBuilder rankGraphBuilder; |
| @@ -135,20 +279,26 @@ TEST_F(RankGraphBuilderTest, Ut_BuildFromRankTable_When_NetLayerInconsistent_Exp | |||
| 135 | { | 279 | { |
| 136 | test::MakeAddress("192.168.200.1", {"0/1"}), | 280 | test::MakeAddress("192.168.200.1", {"0/1"}), |
| 137 | })); | 281 | })); |
| 138 | - EXPECT_THROW(rankGraphBuilder.Build(rankTable, "topo.json", 0), InvalidParamsException); | 282 | + std::unique_ptr<RankGraph> rankGraph; |
| 283 | + EXPECT_NO_THROW(rankGraph = rankGraphBuilder.Build(rankTable, "topo.json", 0)); | ||
| 284 | + EXPECT_NE(rankGraph, nullptr); | ||
| 139 | } | 285 | } |
| 140 | 286 | ||
| 141 | -TEST_F(RankGraphBuilderTest, ut_Build_When_4pRankTable_Expect_Success) | 287 | +TEST_F(RankGraphBuilderTest, Ut_Build_When_TopoWithoutNetLayer_Expect_UseRankTableLayers) |
| 142 | { | 288 | { |
| 143 | PhyTopo::GetInstance()->Clear(); | 289 | PhyTopo::GetInstance()->Clear(); |
| 144 | RankGraphBuilder rankGraphBuilder; | 290 | RankGraphBuilder rankGraphBuilder; |
| 145 | std::unique_ptr<RankGraph> rankGraph | 291 | std::unique_ptr<RankGraph> rankGraph |
| 146 | = rankGraphBuilder.RecoverBuild(test::MakeRankTable4pForBuilder(), test::MakeFourPeerBuilderTopo(), 0); | 292 | = rankGraphBuilder.RecoverBuild(test::MakeRankTable4pForBuilder(), test::MakeFourPeerBuilderTopo(), 0); |
| 147 | - EXPECT_NE(nullptr, rankGraph); | 293 | + ASSERT_NE(nullptr, rankGraph); |
| 294 | + const std::set<u32> expectedLevels = {0, 1, 2}; | ||
| 295 | + EXPECT_EQ(3, rankGraph->GetLevelNum()); | ||
| 296 | + EXPECT_EQ(expectedLevels, rankGraph->GetLevels(0)); | ||
| 148 | std::vector<std::string> netIds = {"az0-rack0", "az0", "all"}; | 297 | std::vector<std::string> netIds = {"az0-rack0", "az0", "all"}; |
| 149 | - for (s32 rankId = 0; rankId < 3; rankId++) { | 298 | + for (s32 rankId = 0; rankId < 4; rankId++) { |
| 150 | for (u32 netLayer = 0; netLayer < 3; netLayer++) { | 299 | for (u32 netLayer = 0; netLayer < 3; netLayer++) { |
| 151 | const NetInstance* fabGroup = rankGraph->GetNetInstanceByRankId(netLayer, rankId); | 300 | const NetInstance* fabGroup = rankGraph->GetNetInstanceByRankId(netLayer, rankId); |
| 301 | + ASSERT_NE(nullptr, fabGroup); | ||
| 152 | EXPECT_EQ(netIds[netLayer], fabGroup->GetNetInstId()); | 302 | EXPECT_EQ(netIds[netLayer], fabGroup->GetNetInstId()); |
| 153 | 303 | ||
| 154 | EXPECT_EQ(true, fabGroup->HasNode(NetInstance::Peer(rankId, 0, 0, 0).GetLocalId())); | 304 | EXPECT_EQ(true, fabGroup->HasNode(NetInstance::Peer(rankId, 0, 0, 0).GetLocalId())); |
| @@ -162,6 +312,11 @@ TEST_F(RankGraphBuilderTest, ut_Build_When_4pRankTable_Expect_Success) | |||
| 162 | } | 312 | } |
| 163 | } | 313 | } |
| 164 | 314 | ||
| 315 | + const NetInstance* layer0 = rankGraph->GetNetInstanceByNetInstId(0, "az0-rack0"); | ||
| 316 | + ASSERT_NE(nullptr, layer0); | ||
| 317 | + EXPECT_TRUE(layer0->fabrics.empty()); | ||
| 318 | + EXPECT_EQ(4, layer0->vGraph.nodes.size()); | ||
| 319 | + | ||
| 165 | std::vector<NetInstance::Path> pathsLayer0 = rankGraph->GetPaths(0, 0, 1); | 320 | std::vector<NetInstance::Path> pathsLayer0 = rankGraph->GetPaths(0, 0, 1); |
| 166 | EXPECT_EQ(1, pathsLayer0.size()); | 321 | EXPECT_EQ(1, pathsLayer0.size()); |
| 167 | // GetPaths检查边0 - 1的level1的边 peer0->net0、net0->peer1、peer0->net1、net1->peer1 | 322 | // GetPaths检查边0 - 1的level1的边 peer0->net0、net0->peer1、peer0->net1、net1->peer1 |
| @@ -186,8 +341,177 @@ TEST_F(RankGraphBuilderTest, ut_Build_When_4pRankTable_Expect_Success) | |||
| 186 | EXPECT_EQ(htonl(0xC0A8650B), pathsLayer1[0].links[1].GetTargetIface()->GetAddr().GetBinaryAddress().addr.s_addr); | 341 | EXPECT_EQ(htonl(0xC0A8650B), pathsLayer1[0].links[1].GetTargetIface()->GetAddr().GetBinaryAddress().addr.s_addr); |
| 187 | 342 | ||
| 188 | std::vector<NetInstance::Path> pathsLayer2 = rankGraph->GetPaths(2, 2, 3); | 343 | std::vector<NetInstance::Path> pathsLayer2 = rankGraph->GetPaths(2, 2, 3); |
| 189 | - EXPECT_EQ(1, pathsLayer1.size()); | 344 | + EXPECT_EQ(1, pathsLayer2.size()); |
| 190 | - EXPECT_EQ(2, pathsLayer1[0].links.size()); | 345 | + EXPECT_EQ(2, pathsLayer2[0].links.size()); |
| 346 | +} | ||
| 347 | + | ||
| 348 | +TEST_F(RankGraphBuilderTest, Ut_RecoverBuild_When_EidSupportsCtpAndRtp_Expect_AllUbProtocols) | ||
| 349 | +{ | ||
| 350 | + DevBaseAttr devBaseAttr{}; | ||
| 351 | + devBaseAttr.ub.priorityInfo[0].tpType.bs.ctp = 1; | ||
| 352 | + devBaseAttr.ub.priorityInfo[Hccl::kRaUbGetTpInfoParamDefaultQos].tpType.bs.rtp = 1; | ||
| 353 | + MockDevBaseAttr(&devBaseAttr); | ||
| 354 | + | ||
| 355 | + RankGraphBuilder rankGraphBuilder; | ||
| 356 | + std::unique_ptr<RankGraph> rankGraph | ||
| 357 | + = rankGraphBuilder.RecoverBuild(MakeOverlappedUbRankTable(1, LinkProtocol::UB_CTP), MakeOverlappedUbTopo(), 0); | ||
| 358 | + | ||
| 359 | + ASSERT_NE(nullptr, rankGraph); | ||
| 360 | + const std::set<u32> expectedLevels = {0, 1}; | ||
| 361 | + EXPECT_EQ(expectedLevels, rankGraph->GetLevels(0)); | ||
| 362 | + CheckOverlappedUbPaths(*rankGraph, 1, {LinkProtocol::UB_CTP, LinkProtocol::UB_TP, LinkProtocol::UB_MEM}, {2, 6}); | ||
| 363 | +} | ||
| 364 | + | ||
| 365 | +TEST_F(RankGraphBuilderTest, Ut_RecoverBuild_When_Layer1And2HaveDuplicatePhyLinks_Expect_KeepOneTopoInst) | ||
| 366 | +{ | ||
| 367 | + DevBaseAttr devBaseAttr{}; | ||
| 368 | + devBaseAttr.ub.priorityInfo[0].tpType.bs.ctp = 1; | ||
| 369 | + devBaseAttr.ub.priorityInfo[Hccl::kRaUbGetTpInfoParamDefaultQos].tpType.bs.rtp = 1; | ||
| 370 | + MockDevBaseAttr(&devBaseAttr, 4U); | ||
| 371 | + | ||
| 372 | + RankGraphBuilder rankGraphBuilder; | ||
| 373 | + std::unique_ptr<RankGraph> rankGraph | ||
| 374 | + = rankGraphBuilder.RecoverBuild(MakeOverlappedUbRankTableForLayer1And2(), MakeOverlappedUbTopo(true, true), 0); | ||
| 375 | + | ||
| 376 | + ASSERT_NE(nullptr, rankGraph); | ||
| 377 | + for (u32 netLayer : {1U, 2U}) { | ||
| 378 | + CheckSingleTopoInst(*rankGraph, netLayer); | ||
| 379 | + CheckOverlappedUbPaths( | ||
| 380 | + *rankGraph, netLayer, {LinkProtocol::UB_CTP, LinkProtocol::UB_TP, LinkProtocol::UB_MEM}, {2, 6}); | ||
| 381 | + } | ||
| 382 | +} | ||
| 383 | + | ||
| 384 | +TEST_F(RankGraphBuilderTest, Ut_RecoverBuild_When_PortsOverlapAndEidsUseTp_Expect_TpLinks) | ||
| 385 | +{ | ||
| 386 | + DevBaseAttr devBaseAttr{}; | ||
| 387 | + devBaseAttr.ub.priorityInfo[Hccl::kRaUbGetTpInfoParamDefaultQos].tpType.bs.rtp = 1; | ||
| 388 | + MockDevBaseAttr(&devBaseAttr); | ||
| 389 | + | ||
| 390 | + RankGraphBuilder rankGraphBuilder; | ||
| 391 | + std::unique_ptr<RankGraph> rankGraph | ||
| 392 | + = rankGraphBuilder.RecoverBuild(MakeOverlappedUbRankTable(2, LinkProtocol::UB_TP), MakeOverlappedUbTopo(), 0); | ||
| 393 | + | ||
| 394 | + ASSERT_NE(nullptr, rankGraph); | ||
| 395 | + CheckOverlappedUbPaths(*rankGraph, 2, {LinkProtocol::UB_TP}, {2, 2}); | ||
| 396 | +} | ||
| 397 | + | ||
| 398 | +TEST_F(RankGraphBuilderTest, Ut_RecoverBuild_When_OnlyRemotePortsOverlapAndEidsUseCtp_Expect_IgnoreTpLinks) | ||
| 399 | +{ | ||
| 400 | + DevBaseAttr devBaseAttr{}; | ||
| 401 | + devBaseAttr.ub.priorityInfo[Hccl::kRaUbGetTpInfoParamDefaultQos].tpType.bs.ctp = 1; | ||
| 402 | + MockDevBaseAttr(&devBaseAttr); | ||
| 403 | + | ||
| 404 | + RankGraphBuilder rankGraphBuilder; | ||
| 405 | + std::unique_ptr<RankGraph> rankGraph = rankGraphBuilder.RecoverBuild( | ||
| 406 | + MakeOverlappedUbRankTable(1, LinkProtocol::UB_CTP), MakeOverlappedUbTopo(false), 0); | ||
| 407 | + | ||
| 408 | + ASSERT_NE(nullptr, rankGraph); | ||
| 409 | + CheckOverlappedUbPaths(*rankGraph, 1, {LinkProtocol::UB_CTP, LinkProtocol::UB_MEM}, {2, 6}); | ||
| 410 | +} | ||
| 411 | + | ||
| 412 | +TEST_F(RankGraphBuilderTest, Ut_RecoverBuild_When_SameTopoInstHasDifferentPlanes_Expect_CreateFabricByPlaneId) | ||
| 413 | +{ | ||
| 414 | + PhyTopo::GetInstance()->Clear(); | ||
| 415 | + const std::string rankTableString = R"({ | ||
| 416 | + "version": "2.0", | ||
| 417 | + "rank_count": 1, | ||
| 418 | + "rank_list": [ | ||
| 419 | + { | ||
| 420 | + "rank_id": 0, | ||
| 421 | + "device_id": 0, | ||
| 422 | + "local_id": 0, | ||
| 423 | + "level_list": [ | ||
| 424 | + { | ||
| 425 | + "net_layer": 0, | ||
| 426 | + "net_instance_id": "rank-group-0", | ||
| 427 | + "net_type": "TOPO_FILE_DESC", | ||
| 428 | + "rank_addr_list": [ | ||
| 429 | + { | ||
| 430 | + "addr_type": "IPV4", | ||
| 431 | + "addr": "192.168.0.1", | ||
| 432 | + "ports": ["0/1"], | ||
| 433 | + "plane_id": "planeA" | ||
| 434 | + }, | ||
| 435 | + { | ||
| 436 | + "addr_type": "IPV4", | ||
| 437 | + "addr": "192.168.0.2", | ||
| 438 | + "ports": ["0/2"], | ||
| 439 | + "plane_id": "planeB" | ||
| 440 | + } | ||
| 441 | + ] | ||
| 442 | + } | ||
| 443 | + ] | ||
| 444 | + } | ||
| 445 | + ] | ||
| 446 | + })"; | ||
| 447 | + const std::string topoString = R"({ | ||
| 448 | + "version": "2.0", | ||
| 449 | + "peer_count": 1, | ||
| 450 | + "peer_list": [{"local_id": 0}], | ||
| 451 | + "edge_count": 2, | ||
| 452 | + "edge_list": [ | ||
| 453 | + { | ||
| 454 | + "link_type": "PEER2NET", | ||
| 455 | + "protocols": ["UB_CTP"], | ||
| 456 | + "topo_type": "CLOS", | ||
| 457 | + "topo_instance_id": 7, | ||
| 458 | + "local_a": 0, | ||
| 459 | + "local_a_ports": ["0/1"], | ||
| 460 | + "position": "DEVICE" | ||
| 461 | + }, | ||
| 462 | + { | ||
| 463 | + "link_type": "PEER2NET", | ||
| 464 | + "protocols": ["UB_CTP"], | ||
| 465 | + "topo_type": "CLOS", | ||
| 466 | + "topo_instance_id": 7, | ||
| 467 | + "local_a": 0, | ||
| 468 | + "local_a_ports": ["0/2"], | ||
| 469 | + "position": "DEVICE" | ||
| 470 | + } | ||
| 471 | + ] | ||
| 472 | + })"; | ||
| 473 | + | ||
| 474 | + JsonParser parser; | ||
| 475 | + RankTableInfo rankTableInfo; | ||
| 476 | + TopoInfo topoInfo; | ||
| 477 | + parser.ParseString(rankTableString, rankTableInfo); | ||
| 478 | + parser.ParseString(topoString, topoInfo); | ||
| 479 | + | ||
| 480 | + RankGraphBuilder rankGraphBuilder; | ||
| 481 | + std::unique_ptr<RankGraph> rankGraph = rankGraphBuilder.RecoverBuild(rankTableInfo, topoInfo, 0); | ||
| 482 | + ASSERT_NE(nullptr, rankGraph); | ||
| 483 | + NetInstance* layer0 = rankGraph->GetNetInstanceByNetInstId(0, "rank-group-0"); | ||
| 484 | + ASSERT_NE(nullptr, layer0); | ||
| 485 | + ASSERT_EQ(2, layer0->GetFabrics().size()); | ||
| 486 | + std::set<PlaneId> planeIds; | ||
| 487 | + for (const auto& fabric : layer0->GetFabrics()) { | ||
| 488 | + ASSERT_NE(nullptr, fabric); | ||
| 489 | + planeIds.insert(fabric->GetPlaneId()); | ||
| 490 | + } | ||
| 491 | + EXPECT_EQ((std::set<PlaneId>{"planeA", "planeB"}), planeIds); | ||
| 492 | +} | ||
| 493 | + | ||
| 494 | +TEST_F(RankGraphBuilderTest, Ut_ConstructConnI_When_PortMapEmpty_Expect_OnlyPcieCreatesD2hIface) | ||
| 495 | +{ | ||
| 496 | + const std::map<std::string, std::vector<IpAddress>> emptyPortAddrMap; | ||
| 497 | + auto pcieIface = std::make_shared<PhyTopo::ConnInterface>( | ||
| 498 | + std::set<std::string>{"0/0"}, AddrPosition::DEVICE, LinkType::PEER2PEER, | ||
| 499 | + std::set<LinkProtocol>{LinkProtocol::PCIE}); | ||
| 500 | + MOCKER(HrtRaSocketGetVnicIpInfos).stubs(); | ||
| 501 | + | ||
| 502 | + auto pcieNetIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(pcieIface, emptyPortAddrMap, TopoType::CLOS, 0, 0); | ||
| 503 | + | ||
| 504 | + ASSERT_EQ(1, pcieNetIfaces.size()); | ||
| 505 | + EXPECT_EQ(std::set<std::string>{"d2h"}, pcieNetIfaces[0]->GetPorts()); | ||
| 506 | + EXPECT_EQ(std::set<LinkProtocol>{LinkProtocol::PCIE}, pcieNetIfaces[0]->GetLinkProtocols()); | ||
| 507 | + | ||
| 508 | + auto unmatchedIface = std::make_shared<PhyTopo::ConnInterface>( | ||
| 509 | + std::set<std::string>{"0/9"}, AddrPosition::DEVICE, LinkType::PEER2PEER, | ||
| 510 | + std::set<LinkProtocol>{LinkProtocol::UB_CTP}); | ||
| 511 | + auto unmatchedNetIfaces | ||
| 512 | + = ConstructConnIFromPhyTopoConnIAndPortMap(unmatchedIface, emptyPortAddrMap, TopoType::CLOS, 0, 0); | ||
| 513 | + | ||
| 514 | + EXPECT_TRUE(unmatchedNetIfaces.empty()); | ||
| 191 | } | 515 | } |
| 192 | 516 | ||
| 193 | TEST_F(RankGraphBuilderTest, Ut_RankGraphBuilderRecoverBuild_When_Invalid_Expect_InvalidParamsException) | 517 | TEST_F(RankGraphBuilderTest, Ut_RankGraphBuilderRecoverBuild_When_Invalid_Expect_InvalidParamsException) |
| @@ -40,7 +40,6 @@ TEST_F(EdgeParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 40 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); | 40 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); |
| 41 | 41 | ||
| 42 | std::string edgeString = R"({ | 42 | std::string edgeString = R"({ |
| 43 | - "net_layer": 0, | ||
| 44 | "link_type": "PEER2PEER", | 43 | "link_type": "PEER2PEER", |
| 45 | "protocols": ["UB_CTP"], | 44 | "protocols": ["UB_CTP"], |
| 46 | "topo_type": "1DMESH", | 45 | "topo_type": "1DMESH", |
| @@ -57,7 +56,6 @@ TEST_F(EdgeParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 57 | topoParser.ParseString(edgeString, edgeInfo); | 56 | topoParser.ParseString(edgeString, edgeInfo); |
| 58 | 57 | ||
| 59 | EdgeInfo edge0; | 58 | EdgeInfo edge0; |
| 60 | - edge0.netLayer = 0; | ||
| 61 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 59 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 62 | edge0.linkType = LinkType::PEER2PEER; | 60 | edge0.linkType = LinkType::PEER2PEER; |
| 63 | edge0.topoType = TopoType::MESH_1D; | 61 | edge0.topoType = TopoType::MESH_1D; |
| @@ -101,7 +99,6 @@ TEST_F(EdgeParserTest, Ut_Deserialize_When_OptionalFieldsMissing_Expect_Success) | |||
| 101 | topoParser.ParseString(edgeString, edgeInfo); | 99 | topoParser.ParseString(edgeString, edgeInfo); |
| 102 | 100 | ||
| 103 | EdgeInfo edge0; | 101 | EdgeInfo edge0; |
| 104 | - edge0.netLayer = 0; | ||
| 105 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 102 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 106 | edge0.linkType = LinkType::PEER2PEER; | 103 | edge0.linkType = LinkType::PEER2PEER; |
| 107 | edge0.topoType = TopoType::CLOS; | 104 | edge0.topoType = TopoType::CLOS; |
| @@ -139,7 +136,6 @@ TEST_F(EdgeParserTest, Ut_Deserialize_When_PEER2NET_ExistB_Expect_Warning) | |||
| 139 | topoParser.ParseString(edgeString, edgeInfo); | 136 | topoParser.ParseString(edgeString, edgeInfo); |
| 140 | 137 | ||
| 141 | EdgeInfo edge0; | 138 | EdgeInfo edge0; |
| 142 | - edge0.netLayer = 0; | ||
| 143 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 139 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 144 | edge0.linkType = LinkType::PEER2NET; | 140 | edge0.linkType = LinkType::PEER2NET; |
| 145 | edge0.topoType = TopoType::MESH_1D; | 141 | edge0.topoType = TopoType::MESH_1D; |
| @@ -173,7 +169,6 @@ TEST_F(EdgeParserTest, Ut_Deserialize_When_NormalPeer2Net_Expect_Success) | |||
| 173 | topoParser.ParseString(edgeString, edgeInfo); | 169 | topoParser.ParseString(edgeString, edgeInfo); |
| 174 | 170 | ||
| 175 | EdgeInfo edge0; | 171 | EdgeInfo edge0; |
| 176 | - edge0.netLayer = 0; | ||
| 177 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 172 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 178 | edge0.linkType = LinkType::PEER2NET; | 173 | edge0.linkType = LinkType::PEER2NET; |
| 179 | edge0.topoType = TopoType::MESH_1D; | 174 | edge0.topoType = TopoType::MESH_1D; |
| @@ -202,14 +197,13 @@ TEST_F(EdgeParserTest, Ut_Deserialize_When_NeededFieldMissing_Expect_Exception) | |||
| 202 | EXPECT_THROW(edgeParser.ParseString(edgeString, edgeInfo), InvalidParamsException); | 197 | EXPECT_THROW(edgeParser.ParseString(edgeString, edgeInfo), InvalidParamsException); |
| 203 | } | 198 | } |
| 204 | 199 | ||
| 205 | -// net_layer = 8 | 200 | +// 旧 topo.json 中不同或越界的 net_layer 都应被忽略,解析结果与不带该字段时一致 |
| 206 | -TEST_F(EdgeParserTest, Ut_Deserialize_When_InvalidNetLayer_Expect_Exception) | 201 | +TEST_F(EdgeParserTest, Ut_Deserialize_When_LegacyNetLayerDifferentOrOutOfRange_Expect_SameEdge) |
| 207 | { | 202 | { |
| 208 | DevType devType = DevType::DEV_TYPE_910A; | 203 | DevType devType = DevType::DEV_TYPE_910A; |
| 209 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); | 204 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); |
| 210 | 205 | ||
| 211 | - std::string edgeString = R"({ | 206 | + std::string edgeStringWithoutNetLayer = R"({ |
| 212 | - "net_layer": 8, | ||
| 213 | "link_type": "PEER2PEER", | 207 | "link_type": "PEER2PEER", |
| 214 | "protocols": ["UB_CTP"], | 208 | "protocols": ["UB_CTP"], |
| 215 | "topo_type": "1DMESH", | 209 | "topo_type": "1DMESH", |
| @@ -221,9 +215,21 @@ TEST_F(EdgeParserTest, Ut_Deserialize_When_InvalidNetLayer_Expect_Exception) | |||
| 221 | "position": "DEVICE" | 215 | "position": "DEVICE" |
| 222 | })"; | 216 | })"; |
| 223 | 217 | ||
| 218 | + nlohmann::json edgeJsonWithoutNetLayer = nlohmann::json::parse(edgeStringWithoutNetLayer); | ||
| 219 | + nlohmann::json edgeJsonWithDifferentNetLayer = edgeJsonWithoutNetLayer; | ||
| 220 | + nlohmann::json edgeJsonWithOutOfRangeNetLayer = edgeJsonWithoutNetLayer; | ||
| 221 | + edgeJsonWithDifferentNetLayer["net_layer"] = 1; | ||
| 222 | + edgeJsonWithOutOfRangeNetLayer["net_layer"] = 8; | ||
| 223 | + | ||
| 224 | JsonParser edgeParser; | 224 | JsonParser edgeParser; |
| 225 | - EdgeInfo edgeInfo; | 225 | + EdgeInfo edgeWithoutNetLayer; |
| 226 | - EXPECT_THROW(edgeParser.ParseString(edgeString, edgeInfo), InvalidParamsException); | 226 | + EdgeInfo edgeWithDifferentNetLayer; |
| 227 | + EdgeInfo edgeWithOutOfRangeNetLayer; | ||
| 228 | + EXPECT_NO_THROW(edgeParser.ParseString(edgeStringWithoutNetLayer, edgeWithoutNetLayer)); | ||
| 229 | + EXPECT_NO_THROW(edgeParser.ParseString(edgeJsonWithDifferentNetLayer.dump(), edgeWithDifferentNetLayer)); | ||
| 230 | + EXPECT_NO_THROW(edgeParser.ParseString(edgeJsonWithOutOfRangeNetLayer.dump(), edgeWithOutOfRangeNetLayer)); | ||
| 231 | + EXPECT_TRUE(edgeWithoutNetLayer == edgeWithDifferentNetLayer); | ||
| 232 | + EXPECT_TRUE(edgeWithoutNetLayer == edgeWithOutOfRangeNetLayer); | ||
| 227 | } | 233 | } |
| 228 | 234 | ||
| 229 | // 无效的LinkProtocol | 235 | // 无效的LinkProtocol |
| @@ -447,7 +453,6 @@ TEST_F(EdgeParserTest, Ut_Deserialize_When_InvalidPosition_Expect_Exception) | |||
| 447 | TEST_F(EdgeParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success) | 453 | TEST_F(EdgeParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success) |
| 448 | { | 454 | { |
| 449 | EdgeInfo edge0; | 455 | EdgeInfo edge0; |
| 450 | - edge0.netLayer = 0; | ||
| 451 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 456 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 452 | edge0.linkType = LinkType::PEER2PEER; | 457 | edge0.linkType = LinkType::PEER2PEER; |
| 453 | edge0.topoType = TopoType::MESH_1D; | 458 | edge0.topoType = TopoType::MESH_1D; |
| @@ -464,4 +469,12 @@ TEST_F(EdgeParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 464 | 469 | ||
| 465 | EdgeInfo edgeInfoRebuild(binStream); | 470 | EdgeInfo edgeInfoRebuild(binStream); |
| 466 | EXPECT_EQ(edgeInfoRebuild.Describe(), edge0.Describe()); | 471 | EXPECT_EQ(edgeInfoRebuild.Describe(), edge0.Describe()); |
| 472 | + | ||
| 473 | + BinaryStream layoutStream; | ||
| 474 | + edge0.GetBinStream(layoutStream); | ||
| 475 | + u32 binaryLayer = 0; | ||
| 476 | + u32 linkType = 0; | ||
| 477 | + layoutStream >> binaryLayer >> linkType; | ||
| 478 | + EXPECT_EQ(binaryLayer, 0); | ||
| 479 | + EXPECT_EQ(linkType, static_cast<u32>(edge0.linkType)); | ||
| 467 | } | 480 | } |
| @@ -49,6 +49,28 @@ std::string BuildLargeTopoString() | |||
| 49 | } | 49 | } |
| 50 | } // namespace | 50 | } // namespace |
| 51 | 51 | ||
| 52 | +namespace { | ||
| 53 | +void WriteLegacyEdge(BinaryStream& binaryStream, u32 binaryLayer, const EdgeInfo& edge) | ||
| 54 | +{ | ||
| 55 | + binaryStream << binaryLayer << static_cast<u32>(edge.linkType) << static_cast<u32>(edge.topoType) | ||
| 56 | + << edge.topoInstId; | ||
| 57 | + binaryStream << edge.protocols.size(); | ||
| 58 | + for (const auto& protocol : edge.protocols) { | ||
| 59 | + binaryStream << static_cast<u32>(protocol); | ||
| 60 | + } | ||
| 61 | + binaryStream << edge.localA << edge.localB; | ||
| 62 | + binaryStream << edge.localAPorts.size(); | ||
| 63 | + for (const auto& port : edge.localAPorts) { | ||
| 64 | + binaryStream << port; | ||
| 65 | + } | ||
| 66 | + binaryStream << edge.localBPorts.size(); | ||
| 67 | + for (const auto& port : edge.localBPorts) { | ||
| 68 | + binaryStream << port; | ||
| 69 | + } | ||
| 70 | + binaryStream << static_cast<u32>(edge.position); | ||
| 71 | +} | ||
| 72 | +} // namespace | ||
| 73 | + | ||
| 52 | class TopoParserTest : public testing::Test { | 74 | class TopoParserTest : public testing::Test { |
| 53 | protected: | 75 | protected: |
| 54 | static void SetUpTestCase() { std::cout << "TopoParserTest SetUP" << std::endl; } | 76 | static void SetUpTestCase() { std::cout << "TopoParserTest SetUP" << std::endl; } |
| @@ -157,11 +179,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 157 | expectTopoInfo.peers.emplace_back(peer2); | 179 | expectTopoInfo.peers.emplace_back(peer2); |
| 158 | 180 | ||
| 159 | expectTopoInfo.edgeCount = 5; | 181 | expectTopoInfo.edgeCount = 5; |
| 160 | - expectTopoInfo.edges[0] = std::vector<EdgeInfo>(); | ||
| 161 | - expectTopoInfo.edges[1] = std::vector<EdgeInfo>(); | ||
| 162 | - expectTopoInfo.edges[2] = std::vector<EdgeInfo>(); | ||
| 163 | EdgeInfo edge0; | 182 | EdgeInfo edge0; |
| 164 | - edge0.netLayer = 0; | ||
| 165 | edge0.linkType = LinkType::PEER2PEER; | 183 | edge0.linkType = LinkType::PEER2PEER; |
| 166 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 184 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 167 | edge0.topoType = TopoType::MESH_1D; | 185 | edge0.topoType = TopoType::MESH_1D; |
| @@ -171,10 +189,9 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 171 | edge0.localB = 1; | 189 | edge0.localB = 1; |
| 172 | edge0.localBPorts.emplace("0/1"); | 190 | edge0.localBPorts.emplace("0/1"); |
| 173 | edge0.position = AddrPosition::DEVICE; | 191 | edge0.position = AddrPosition::DEVICE; |
| 174 | - expectTopoInfo.edges[0].emplace_back(edge0); | 192 | + expectTopoInfo.edges.emplace_back(edge0); |
| 175 | 193 | ||
| 176 | EdgeInfo edge1; | 194 | EdgeInfo edge1; |
| 177 | - edge1.netLayer = 0; | ||
| 178 | edge1.linkType = LinkType::PEER2PEER; | 195 | edge1.linkType = LinkType::PEER2PEER; |
| 179 | edge1.protocols.emplace(LinkProtocol::UB_MEM); | 196 | edge1.protocols.emplace(LinkProtocol::UB_MEM); |
| 180 | edge1.topoType = TopoType::MESH_1D; | 197 | edge1.topoType = TopoType::MESH_1D; |
| @@ -184,10 +201,9 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 184 | edge1.localB = 2; | 201 | edge1.localB = 2; |
| 185 | edge1.localBPorts.emplace("0/1"); | 202 | edge1.localBPorts.emplace("0/1"); |
| 186 | edge1.position = AddrPosition::DEVICE; | 203 | edge1.position = AddrPosition::DEVICE; |
| 187 | - expectTopoInfo.edges[0].emplace_back(edge1); | 204 | + expectTopoInfo.edges.emplace_back(edge1); |
| 188 | 205 | ||
| 189 | EdgeInfo edge2; | 206 | EdgeInfo edge2; |
| 190 | - edge2.netLayer = 0; | ||
| 191 | edge2.linkType = LinkType::PEER2NET; | 207 | edge2.linkType = LinkType::PEER2NET; |
| 192 | edge2.protocols.emplace(LinkProtocol::UB_CTP); | 208 | edge2.protocols.emplace(LinkProtocol::UB_CTP); |
| 193 | edge2.topoType = TopoType::MESH_1D; | 209 | edge2.topoType = TopoType::MESH_1D; |
| @@ -195,10 +211,9 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 195 | edge2.localA = 0; | 211 | edge2.localA = 0; |
| 196 | edge2.localAPorts.emplace("0/0"); | 212 | edge2.localAPorts.emplace("0/0"); |
| 197 | edge2.position = AddrPosition::HOST; | 213 | edge2.position = AddrPosition::HOST; |
| 198 | - expectTopoInfo.edges[0].emplace_back(edge2); | 214 | + expectTopoInfo.edges.emplace_back(edge2); |
| 199 | 215 | ||
| 200 | EdgeInfo edge3; | 216 | EdgeInfo edge3; |
| 201 | - edge3.netLayer = 1; | ||
| 202 | edge3.linkType = LinkType::PEER2PEER; | 217 | edge3.linkType = LinkType::PEER2PEER; |
| 203 | edge3.protocols.emplace(LinkProtocol::UB_TP); | 218 | edge3.protocols.emplace(LinkProtocol::UB_TP); |
| 204 | edge3.topoType = TopoType::MESH_1D; | 219 | edge3.topoType = TopoType::MESH_1D; |
| @@ -208,10 +223,9 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 208 | edge3.localB = 2; | 223 | edge3.localB = 2; |
| 209 | edge3.localBPorts.emplace("0/1"); | 224 | edge3.localBPorts.emplace("0/1"); |
| 210 | edge3.position = AddrPosition::DEVICE; | 225 | edge3.position = AddrPosition::DEVICE; |
| 211 | - expectTopoInfo.edges[1].emplace_back(edge3); | 226 | + expectTopoInfo.edges.emplace_back(edge3); |
| 212 | 227 | ||
| 213 | EdgeInfo edge4; | 228 | EdgeInfo edge4; |
| 214 | - edge4.netLayer = 2; | ||
| 215 | edge4.linkType = LinkType::PEER2NET; | 229 | edge4.linkType = LinkType::PEER2NET; |
| 216 | edge4.protocols.emplace(LinkProtocol::ROCE); | 230 | edge4.protocols.emplace(LinkProtocol::ROCE); |
| 217 | edge4.topoType = TopoType::CLOS; | 231 | edge4.topoType = TopoType::CLOS; |
| @@ -219,7 +233,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 219 | edge4.localA = 0; | 233 | edge4.localA = 0; |
| 220 | edge4.localAPorts.emplace("0/0"); | 234 | edge4.localAPorts.emplace("0/0"); |
| 221 | edge4.position = AddrPosition::DEVICE; | 235 | edge4.position = AddrPosition::DEVICE; |
| 222 | - expectTopoInfo.edges[2].emplace_back(edge4); | 236 | + expectTopoInfo.edges.emplace_back(edge4); |
| 223 | 237 | ||
| 224 | EXPECT_EQ(topoInfo.version, expectTopoInfo.version); | 238 | EXPECT_EQ(topoInfo.version, expectTopoInfo.version); |
| 225 | EXPECT_EQ(topoInfo.peerCount, expectTopoInfo.peerCount); | 239 | EXPECT_EQ(topoInfo.peerCount, expectTopoInfo.peerCount); |
| @@ -230,24 +244,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_Normal_Expect_Success) | |||
| 230 | EXPECT_EQ(topoInfo.edgeCount, expectTopoInfo.edgeCount); | 244 | EXPECT_EQ(topoInfo.edgeCount, expectTopoInfo.edgeCount); |
| 231 | EXPECT_EQ(topoInfo.edges.size(), expectTopoInfo.edges.size()); | 245 | EXPECT_EQ(topoInfo.edges.size(), expectTopoInfo.edges.size()); |
| 232 | 246 | ||
| 233 | - auto it_topo_edges = topoInfo.edges.begin(); | 247 | + EXPECT_EQ(topoInfo.edges, expectTopoInfo.edges); |
| 234 | - auto it_expect_edges = expectTopoInfo.edges.begin(); | ||
| 235 | - for (; it_topo_edges != topoInfo.edges.end(); it_topo_edges++, it_expect_edges++) { | ||
| 236 | - EXPECT_EQ(it_topo_edges->first, it_expect_edges->first); | ||
| 237 | - EXPECT_EQ((it_topo_edges->second).size(), (it_expect_edges->second).size()); | ||
| 238 | - for (u32 i = 0; i < (it_topo_edges->second).size(); i++) { | ||
| 239 | - EXPECT_EQ((it_topo_edges->second)[i].netLayer, (it_expect_edges->second)[i].netLayer); | ||
| 240 | - EXPECT_EQ((it_topo_edges->second)[i].protocols, (it_expect_edges->second)[i].protocols); | ||
| 241 | - EXPECT_EQ((it_topo_edges->second)[i].linkType, (it_expect_edges->second)[i].linkType); | ||
| 242 | - EXPECT_EQ((it_topo_edges->second)[i].topoType, (it_expect_edges->second)[i].topoType); | ||
| 243 | - EXPECT_EQ((it_topo_edges->second)[i].topoInstId, (it_expect_edges->second)[i].topoInstId); | ||
| 244 | - EXPECT_EQ((it_topo_edges->second)[i].localA, (it_expect_edges->second)[i].localA); | ||
| 245 | - EXPECT_EQ((it_topo_edges->second)[i].localAPorts, (it_expect_edges->second)[i].localAPorts); | ||
| 246 | - EXPECT_EQ((it_topo_edges->second)[i].localB, (it_expect_edges->second)[i].localB); | ||
| 247 | - EXPECT_EQ((it_topo_edges->second)[i].localBPorts, (it_expect_edges->second)[i].localBPorts); | ||
| 248 | - EXPECT_EQ((it_topo_edges->second)[i].position, (it_expect_edges->second)[i].position); | ||
| 249 | - } | ||
| 250 | - } | ||
| 251 | 248 | ||
| 252 | EXPECT_EQ(topoInfo.Describe(), expectTopoInfo.Describe()); | 249 | EXPECT_EQ(topoInfo.Describe(), expectTopoInfo.Describe()); |
| 253 | } | 250 | } |
| @@ -473,7 +470,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_EdgesSizeUnequalToEdgeCount_Expect_Ex | |||
| 473 | } | 470 | } |
| 474 | 471 | ||
| 475 | // 重复的边 PEER2PEER,localA和localB对调 | 472 | // 重复的边 PEER2PEER,localA和localB对调 |
| 476 | -TEST_F(TopoParserTest, Ut_Deserialize_When_DuplicateEdge_Expect_Exception) | 473 | +TEST_F(TopoParserTest, Ut_Deserialize_When_DuplicateEdge_Expect_Merged) |
| 477 | { | 474 | { |
| 478 | DevType devType = DevType::DEV_TYPE_910A; | 475 | DevType devType = DevType::DEV_TYPE_910A; |
| 479 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); | 476 | MOCKER(HrtGetDeviceType).stubs().will(returnValue(devType)); |
| @@ -502,7 +499,7 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_DuplicateEdge_Expect_Exception) | |||
| 502 | "position": "DEVICE" | 499 | "position": "DEVICE" |
| 503 | }, | 500 | }, |
| 504 | { | 501 | { |
| 505 | - "net_layer": 0, | 502 | + "net_layer": 7, |
| 506 | "link_type": "PEER2PEER", | 503 | "link_type": "PEER2PEER", |
| 507 | "protocols": ["UB_CTP"], | 504 | "protocols": ["UB_CTP"], |
| 508 | "topo_type": "1DMESH", | 505 | "topo_type": "1DMESH", |
| @@ -518,7 +515,11 @@ TEST_F(TopoParserTest, Ut_Deserialize_When_DuplicateEdge_Expect_Exception) | |||
| 518 | 515 | ||
| 519 | JsonParser topoParser; | 516 | JsonParser topoParser; |
| 520 | TopoInfo topoInfo; | 517 | TopoInfo topoInfo; |
| 521 | - EXPECT_THROW(topoParser.ParseString(topoString, topoInfo), InvalidParamsException); | 518 | + EXPECT_NO_THROW(topoParser.ParseString(topoString, topoInfo)); |
| 519 | + EXPECT_EQ(topoInfo.edgeCount, 1); | ||
| 520 | + ASSERT_EQ(topoInfo.edges.size(), 1); | ||
| 521 | + EXPECT_EQ(topoInfo.edges[0].localA, 0); | ||
| 522 | + EXPECT_EQ(topoInfo.edges[0].localB, 1); | ||
| 522 | } | 523 | } |
| 523 | 524 | ||
| 524 | // Endpoint的localId无效 | 525 | // Endpoint的localId无效 |
| @@ -697,11 +698,7 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 697 | expectTopoInfo.peers.emplace_back(peer2); | 698 | expectTopoInfo.peers.emplace_back(peer2); |
| 698 | 699 | ||
| 699 | expectTopoInfo.edgeCount = 5; | 700 | expectTopoInfo.edgeCount = 5; |
| 700 | - expectTopoInfo.edges[0] = std::vector<EdgeInfo>(); | ||
| 701 | - expectTopoInfo.edges[1] = std::vector<EdgeInfo>(); | ||
| 702 | - expectTopoInfo.edges[2] = std::vector<EdgeInfo>(); | ||
| 703 | EdgeInfo edge0; | 701 | EdgeInfo edge0; |
| 704 | - edge0.netLayer = 0; | ||
| 705 | edge0.linkType = LinkType::PEER2PEER; | 702 | edge0.linkType = LinkType::PEER2PEER; |
| 706 | edge0.protocols.emplace(LinkProtocol::UB_CTP); | 703 | edge0.protocols.emplace(LinkProtocol::UB_CTP); |
| 707 | edge0.topoType = TopoType::MESH_1D; | 704 | edge0.topoType = TopoType::MESH_1D; |
| @@ -711,10 +708,9 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 711 | edge0.localB = 1; | 708 | edge0.localB = 1; |
| 712 | edge0.localBPorts.emplace("0/1"); | 709 | edge0.localBPorts.emplace("0/1"); |
| 713 | edge0.position = AddrPosition::DEVICE; | 710 | edge0.position = AddrPosition::DEVICE; |
| 714 | - expectTopoInfo.edges[0].emplace_back(edge0); | 711 | + expectTopoInfo.edges.emplace_back(edge0); |
| 715 | 712 | ||
| 716 | EdgeInfo edge1; | 713 | EdgeInfo edge1; |
| 717 | - edge1.netLayer = 0; | ||
| 718 | edge1.linkType = LinkType::PEER2PEER; | 714 | edge1.linkType = LinkType::PEER2PEER; |
| 719 | edge1.protocols.emplace(LinkProtocol::UB_MEM); | 715 | edge1.protocols.emplace(LinkProtocol::UB_MEM); |
| 720 | edge1.topoType = TopoType::MESH_1D; | 716 | edge1.topoType = TopoType::MESH_1D; |
| @@ -724,10 +720,9 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 724 | edge1.localB = 2; | 720 | edge1.localB = 2; |
| 725 | edge1.localBPorts.emplace("0/1"); | 721 | edge1.localBPorts.emplace("0/1"); |
| 726 | edge1.position = AddrPosition::DEVICE; | 722 | edge1.position = AddrPosition::DEVICE; |
| 727 | - expectTopoInfo.edges[0].emplace_back(edge1); | 723 | + expectTopoInfo.edges.emplace_back(edge1); |
| 728 | 724 | ||
| 729 | EdgeInfo edge2; | 725 | EdgeInfo edge2; |
| 730 | - edge2.netLayer = 0; | ||
| 731 | edge2.linkType = LinkType::PEER2NET; | 726 | edge2.linkType = LinkType::PEER2NET; |
| 732 | edge2.protocols.emplace(LinkProtocol::UB_CTP); | 727 | edge2.protocols.emplace(LinkProtocol::UB_CTP); |
| 733 | edge2.topoType = TopoType::MESH_1D; | 728 | edge2.topoType = TopoType::MESH_1D; |
| @@ -735,10 +730,9 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 735 | edge2.localA = 0; | 730 | edge2.localA = 0; |
| 736 | edge2.localAPorts.emplace("0/0"); | 731 | edge2.localAPorts.emplace("0/0"); |
| 737 | edge2.position = AddrPosition::HOST; | 732 | edge2.position = AddrPosition::HOST; |
| 738 | - expectTopoInfo.edges[0].emplace_back(edge2); | 733 | + expectTopoInfo.edges.emplace_back(edge2); |
| 739 | 734 | ||
| 740 | EdgeInfo edge3; | 735 | EdgeInfo edge3; |
| 741 | - edge3.netLayer = 1; | ||
| 742 | edge3.linkType = LinkType::PEER2PEER; | 736 | edge3.linkType = LinkType::PEER2PEER; |
| 743 | edge3.protocols.emplace(LinkProtocol::UB_TP); | 737 | edge3.protocols.emplace(LinkProtocol::UB_TP); |
| 744 | edge3.topoType = TopoType::MESH_1D; | 738 | edge3.topoType = TopoType::MESH_1D; |
| @@ -748,10 +742,9 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 748 | edge3.localB = 2; | 742 | edge3.localB = 2; |
| 749 | edge3.localBPorts.emplace("0/1"); | 743 | edge3.localBPorts.emplace("0/1"); |
| 750 | edge3.position = AddrPosition::DEVICE; | 744 | edge3.position = AddrPosition::DEVICE; |
| 751 | - expectTopoInfo.edges[1].emplace_back(edge3); | 745 | + expectTopoInfo.edges.emplace_back(edge3); |
| 752 | 746 | ||
| 753 | EdgeInfo edge4; | 747 | EdgeInfo edge4; |
| 754 | - edge4.netLayer = 2; | ||
| 755 | edge4.linkType = LinkType::PEER2NET; | 748 | edge4.linkType = LinkType::PEER2NET; |
| 756 | edge4.protocols.emplace(LinkProtocol::ROCE); | 749 | edge4.protocols.emplace(LinkProtocol::ROCE); |
| 757 | edge4.topoType = TopoType::CLOS; | 750 | edge4.topoType = TopoType::CLOS; |
| @@ -759,12 +752,35 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 759 | edge4.localA = 0; | 752 | edge4.localA = 0; |
| 760 | edge4.localAPorts.emplace("0/0"); | 753 | edge4.localAPorts.emplace("0/0"); |
| 761 | edge4.position = AddrPosition::DEVICE; | 754 | edge4.position = AddrPosition::DEVICE; |
| 762 | - expectTopoInfo.edges[2].emplace_back(edge4); | 755 | + expectTopoInfo.edges.emplace_back(edge4); |
| 763 | 756 | ||
| 764 | BinaryStream binStream; | 757 | BinaryStream binStream; |
| 765 | expectTopoInfo.GetBinStream(binStream); | 758 | expectTopoInfo.GetBinStream(binStream); |
| 766 | TopoInfo reBuildTopo(binStream); | 759 | TopoInfo reBuildTopo(binStream); |
| 767 | 760 | ||
| 761 | + BinaryStream layoutStream; | ||
| 762 | + expectTopoInfo.GetBinStream(layoutStream); | ||
| 763 | + std::string binaryVersion; | ||
| 764 | + u32 binaryPeerCount = 0; | ||
| 765 | + u32 binaryEdgeCount = 0; | ||
| 766 | + size_t binaryPeerSize = 0; | ||
| 767 | + layoutStream >> binaryVersion >> binaryPeerCount >> binaryEdgeCount >> binaryPeerSize; | ||
| 768 | + EXPECT_EQ(binaryVersion, expectTopoInfo.version); | ||
| 769 | + EXPECT_EQ(binaryPeerCount, expectTopoInfo.peerCount); | ||
| 770 | + EXPECT_EQ(binaryEdgeCount, expectTopoInfo.edgeCount); | ||
| 771 | + EXPECT_EQ(binaryPeerSize, expectTopoInfo.peers.size()); | ||
| 772 | + for (size_t i = 0; i < binaryPeerSize; i++) { | ||
| 773 | + PeerInfo binaryPeer(layoutStream); | ||
| 774 | + EXPECT_EQ(binaryPeer.localId, expectTopoInfo.peers[i].localId); | ||
| 775 | + } | ||
| 776 | + size_t edgeGroupCount = 0; | ||
| 777 | + u32 binaryLayer = 0; | ||
| 778 | + size_t groupEdgeCount = 0; | ||
| 779 | + layoutStream >> edgeGroupCount >> binaryLayer >> groupEdgeCount; | ||
| 780 | + EXPECT_EQ(edgeGroupCount, 1); | ||
| 781 | + EXPECT_EQ(binaryLayer, 0); | ||
| 782 | + EXPECT_EQ(groupEdgeCount, expectTopoInfo.edges.size()); | ||
| 783 | + | ||
| 768 | EXPECT_EQ(expectTopoInfo.version, reBuildTopo.version); | 784 | EXPECT_EQ(expectTopoInfo.version, reBuildTopo.version); |
| 769 | EXPECT_EQ(expectTopoInfo.peerCount, reBuildTopo.peerCount); | 785 | EXPECT_EQ(expectTopoInfo.peerCount, reBuildTopo.peerCount); |
| 770 | EXPECT_EQ(expectTopoInfo.peers.size(), reBuildTopo.peers.size()); | 786 | EXPECT_EQ(expectTopoInfo.peers.size(), reBuildTopo.peers.size()); |
| @@ -774,28 +790,110 @@ TEST_F(TopoParserTest, Ut_BinaryStream_When_GetBinStreamToReBuild_Expect_Success | |||
| 774 | EXPECT_EQ(expectTopoInfo.edgeCount, reBuildTopo.edgeCount); | 790 | EXPECT_EQ(expectTopoInfo.edgeCount, reBuildTopo.edgeCount); |
| 775 | EXPECT_EQ(expectTopoInfo.edges.size(), reBuildTopo.edges.size()); | 791 | EXPECT_EQ(expectTopoInfo.edges.size(), reBuildTopo.edges.size()); |
| 776 | 792 | ||
| 777 | - auto it_topo_edges = expectTopoInfo.edges.begin(); | 793 | + EXPECT_EQ(expectTopoInfo.edges, reBuildTopo.edges); |
| 778 | - auto it_expect_edges = reBuildTopo.edges.begin(); | ||
| 779 | - for (; it_topo_edges != expectTopoInfo.edges.end(); it_topo_edges++, it_expect_edges++) { | ||
| 780 | - EXPECT_EQ(it_topo_edges->first, it_expect_edges->first); | ||
| 781 | - EXPECT_EQ((it_topo_edges->second).size(), (it_expect_edges->second).size()); | ||
| 782 | - for (u32 i = 0; i < (it_topo_edges->second).size(); i++) { | ||
| 783 | - EXPECT_EQ((it_topo_edges->second)[i].netLayer, (it_expect_edges->second)[i].netLayer); | ||
| 784 | - EXPECT_EQ((it_topo_edges->second)[i].protocols, (it_expect_edges->second)[i].protocols); | ||
| 785 | - EXPECT_EQ((it_topo_edges->second)[i].linkType, (it_expect_edges->second)[i].linkType); | ||
| 786 | - EXPECT_EQ((it_topo_edges->second)[i].topoType, (it_expect_edges->second)[i].topoType); | ||
| 787 | - EXPECT_EQ((it_topo_edges->second)[i].topoInstId, (it_expect_edges->second)[i].topoInstId); | ||
| 788 | - EXPECT_EQ((it_topo_edges->second)[i].localA, (it_expect_edges->second)[i].localA); | ||
| 789 | - EXPECT_EQ((it_topo_edges->second)[i].localAPorts, (it_expect_edges->second)[i].localAPorts); | ||
| 790 | - EXPECT_EQ((it_topo_edges->second)[i].localB, (it_expect_edges->second)[i].localB); | ||
| 791 | - EXPECT_EQ((it_topo_edges->second)[i].localBPorts, (it_expect_edges->second)[i].localBPorts); | ||
| 792 | - EXPECT_EQ((it_topo_edges->second)[i].position, (it_expect_edges->second)[i].position); | ||
| 793 | - } | ||
| 794 | - } | ||
| 795 | 794 | ||
| 796 | EXPECT_EQ(expectTopoInfo.Describe(), reBuildTopo.Describe()); | 795 | EXPECT_EQ(expectTopoInfo.Describe(), reBuildTopo.Describe()); |
| 797 | } | 796 | } |
| 798 | 797 | ||
| 798 | +TEST_F(TopoParserTest, Ut_BinaryStream_When_ReadLegacyGroups_Expect_FlattenedEdges) | ||
| 799 | +{ | ||
| 800 | + TopoInfo expectTopoInfo; | ||
| 801 | + expectTopoInfo.version = "2.0"; | ||
| 802 | + expectTopoInfo.peerCount = 2; | ||
| 803 | + expectTopoInfo.edgeCount = 2; | ||
| 804 | + | ||
| 805 | + PeerInfo peer0; | ||
| 806 | + peer0.localId = 0; | ||
| 807 | + PeerInfo peer1; | ||
| 808 | + peer1.localId = 1; | ||
| 809 | + expectTopoInfo.peers = {peer0, peer1}; | ||
| 810 | + | ||
| 811 | + EdgeInfo edge0; | ||
| 812 | + edge0.linkType = LinkType::PEER2PEER; | ||
| 813 | + edge0.protocols.emplace(LinkProtocol::UB_CTP); | ||
| 814 | + edge0.topoType = TopoType::MESH_1D; | ||
| 815 | + edge0.localA = 0; | ||
| 816 | + edge0.localAPorts.emplace("0/0"); | ||
| 817 | + edge0.localB = 1; | ||
| 818 | + edge0.localBPorts.emplace("0/1"); | ||
| 819 | + edge0.position = AddrPosition::DEVICE; | ||
| 820 | + | ||
| 821 | + EdgeInfo edge1; | ||
| 822 | + edge1.linkType = LinkType::PEER2NET; | ||
| 823 | + edge1.protocols.emplace(LinkProtocol::ROCE); | ||
| 824 | + edge1.topoType = TopoType::CLOS; | ||
| 825 | + edge1.topoInstId = 1; | ||
| 826 | + edge1.localA = 1; | ||
| 827 | + edge1.localAPorts.emplace("1/0"); | ||
| 828 | + edge1.position = AddrPosition::HOST; | ||
| 829 | + expectTopoInfo.edges = {edge0, edge1}; | ||
| 830 | + | ||
| 831 | + BinaryStream legacyStream; | ||
| 832 | + legacyStream << expectTopoInfo.version << expectTopoInfo.peerCount << expectTopoInfo.edgeCount; | ||
| 833 | + legacyStream << expectTopoInfo.peers.size(); | ||
| 834 | + for (const auto& peer : expectTopoInfo.peers) { | ||
| 835 | + peer.GetBinStream(legacyStream); | ||
| 836 | + } | ||
| 837 | + const size_t edgeGroupCount = 2; | ||
| 838 | + const size_t groupEdgeCount = 1; | ||
| 839 | + legacyStream << edgeGroupCount; | ||
| 840 | + legacyStream << static_cast<u32>(1) << groupEdgeCount; | ||
| 841 | + WriteLegacyEdge(legacyStream, 1, edge0); | ||
| 842 | + legacyStream << static_cast<u32>(7) << groupEdgeCount; | ||
| 843 | + WriteLegacyEdge(legacyStream, 7, edge1); | ||
| 844 | + | ||
| 845 | + TopoInfo reBuildTopo(legacyStream); | ||
| 846 | + EXPECT_EQ(reBuildTopo.version, expectTopoInfo.version); | ||
| 847 | + EXPECT_EQ(reBuildTopo.peerCount, expectTopoInfo.peerCount); | ||
| 848 | + EXPECT_EQ(reBuildTopo.edgeCount, expectTopoInfo.edgeCount); | ||
| 849 | + EXPECT_EQ(reBuildTopo.peers.size(), expectTopoInfo.peers.size()); | ||
| 850 | + EXPECT_EQ(reBuildTopo.edges, expectTopoInfo.edges); | ||
| 851 | +} | ||
| 852 | + | ||
| 853 | +TEST_F(TopoParserTest, Ut_BinaryStream_When_LegacyGroupsContainSameEdge_Expect_Merged) | ||
| 854 | +{ | ||
| 855 | + TopoInfo topoInfo; | ||
| 856 | + topoInfo.version = "2.0"; | ||
| 857 | + topoInfo.peerCount = 2; | ||
| 858 | + topoInfo.edgeCount = 2; | ||
| 859 | + | ||
| 860 | + PeerInfo peer0; | ||
| 861 | + peer0.localId = 0; | ||
| 862 | + PeerInfo peer1; | ||
| 863 | + peer1.localId = 1; | ||
| 864 | + topoInfo.peers = {peer0, peer1}; | ||
| 865 | + | ||
| 866 | + EdgeInfo edge; | ||
| 867 | + edge.linkType = LinkType::PEER2PEER; | ||
| 868 | + edge.protocols.emplace(LinkProtocol::UB_CTP); | ||
| 869 | + edge.topoType = TopoType::MESH_1D; | ||
| 870 | + edge.localA = 0; | ||
| 871 | + edge.localAPorts.emplace("0/0"); | ||
| 872 | + edge.localB = 1; | ||
| 873 | + edge.localBPorts.emplace("0/1"); | ||
| 874 | + edge.position = AddrPosition::DEVICE; | ||
| 875 | + | ||
| 876 | + BinaryStream legacyStream; | ||
| 877 | + legacyStream << topoInfo.version << topoInfo.peerCount << topoInfo.edgeCount; | ||
| 878 | + legacyStream << topoInfo.peers.size(); | ||
| 879 | + for (const auto& peer : topoInfo.peers) { | ||
| 880 | + peer.GetBinStream(legacyStream); | ||
| 881 | + } | ||
| 882 | + | ||
| 883 | + const size_t edgeGroupCount = 2; | ||
| 884 | + const size_t groupEdgeCount = 1; | ||
| 885 | + legacyStream << edgeGroupCount; | ||
| 886 | + legacyStream << static_cast<u32>(0) << groupEdgeCount; | ||
| 887 | + WriteLegacyEdge(legacyStream, 0, edge); | ||
| 888 | + legacyStream << static_cast<u32>(7) << groupEdgeCount; | ||
| 889 | + WriteLegacyEdge(legacyStream, 7, edge); | ||
| 890 | + | ||
| 891 | + TopoInfo rebuiltTopo(legacyStream); | ||
| 892 | + EXPECT_EQ(rebuiltTopo.edgeCount, 1); | ||
| 893 | + ASSERT_EQ(rebuiltTopo.edges.size(), 1); | ||
| 894 | + EXPECT_EQ(rebuiltTopo.edges[0], edge); | ||
| 895 | +} | ||
| 896 | + | ||
| 799 | TEST_F(TopoParserTest, Ut_DeserializeBinaryStream_When_Normal_Expect_Success) | 897 | TEST_F(TopoParserTest, Ut_DeserializeBinaryStream_When_Normal_Expect_Success) |
| 800 | { | 898 | { |
| 801 | DevType devType = DevType::DEV_TYPE_910A; | 899 | DevType devType = DevType::DEV_TYPE_910A; |
| @@ -810,9 +810,9 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_EmptyRankLevelInfos_Exp | |||
| 810 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 | 810 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 |
| 811 | } | 811 | } |
| 812 | 812 | ||
| 813 | -TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_NoTopoGraph_Expect_NoThrow) | 813 | +TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_NoMatchingPort_Expect_HostPortUnchanged) |
| 814 | { | 814 | { |
| 815 | - // Given: rankInfo with rankLevelInfos but netLayer doesn't match any built topo graph | 815 | + // Given: the rank address port does not match the HOST+RDMA physical link port |
| 816 | NewRankInfo rankInfo; | 816 | NewRankInfo rankInfo; |
| 817 | rankInfo.rankId = 0; | 817 | rankInfo.rankId = 0; |
| 818 | rankInfo.deviceId = 0; | 818 | rankInfo.deviceId = 0; |
| @@ -821,6 +821,7 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_NoTopoGraph_Expect_NoTh | |||
| 821 | AddressInfo addrInfo; | 821 | AddressInfo addrInfo; |
| 822 | addrInfo.addr = IpAddress("192.168.1.1"); | 822 | addrInfo.addr = IpAddress("192.168.1.1"); |
| 823 | addrInfo.socketPort_ = 0; | 823 | addrInfo.socketPort_ = 0; |
| 824 | + addrInfo.ports.insert("0/0"); | ||
| 824 | RankLevelInfo levelInfo; | 825 | RankLevelInfo levelInfo; |
| 825 | levelInfo.netLayer = 0; | 826 | levelInfo.netLayer = 0; |
| 826 | levelInfo.rankAddrs.push_back(addrInfo); | 827 | levelInfo.rankAddrs.push_back(addrInfo); |
| @@ -830,16 +831,15 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_NoTopoGraph_Expect_NoTh | |||
| 830 | 831 | ||
| 831 | MockTopoPathAndBuild(BuildEmptyTopo); | 832 | MockTopoPathAndBuild(BuildEmptyTopo); |
| 832 | 833 | ||
| 833 | - // When: PhyTopo built but netLayer=0 has no graph → GetTopoGraph returns nullptr | 834 | + // When & Then: the unified physical graph is scanned, but the unmatched port is ignored |
| 834 | - // Then: skip nullptr graph, log debug, continue, return without error | ||
| 835 | EXPECT_NO_THROW(rankInfoDetectClient_->HostListenPortDetect(rankInfo)); | 835 | EXPECT_NO_THROW(rankInfoDetectClient_->HostListenPortDetect(rankInfo)); |
| 836 | EXPECT_EQ(rankInfo.hostPort, DEFAULT_VALUE_TCPPORT); | 836 | EXPECT_EQ(rankInfo.hostPort, DEFAULT_VALUE_TCPPORT); |
| 837 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 | 837 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 |
| 838 | } | 838 | } |
| 839 | 839 | ||
| 840 | -TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_MultipleRankLevelInfos_Expect_NoThrow) | 840 | +TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_MultipleUnmatchedPorts_Expect_HostPortUnchanged) |
| 841 | { | 841 | { |
| 842 | - // Given: multiple rankLevelInfos, none with a matching topo graph | 842 | + // Given: multiple rankLevelInfos, none with a port matching the HOST+RDMA physical link |
| 843 | NewRankInfo rankInfo; | 843 | NewRankInfo rankInfo; |
| 844 | rankInfo.rankId = 0; | 844 | rankInfo.rankId = 0; |
| 845 | rankInfo.deviceId = 0; | 845 | rankInfo.deviceId = 0; |
| @@ -849,6 +849,7 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_MultipleRankLevelInfos_ | |||
| 849 | AddressInfo addrInfo; | 849 | AddressInfo addrInfo; |
| 850 | addrInfo.addr = IpAddress(StringFormat("192.168.%u.1", i + 1)); | 850 | addrInfo.addr = IpAddress(StringFormat("192.168.%u.1", i + 1)); |
| 851 | addrInfo.socketPort_ = 0; | 851 | addrInfo.socketPort_ = 0; |
| 852 | + addrInfo.ports.insert(StringFormat("2/%u", i)); | ||
| 852 | RankLevelInfo levelInfo; | 853 | RankLevelInfo levelInfo; |
| 853 | levelInfo.netLayer = i; | 854 | levelInfo.netLayer = i; |
| 854 | levelInfo.rankAddrs.push_back(addrInfo); | 855 | levelInfo.rankAddrs.push_back(addrInfo); |
| @@ -859,7 +860,7 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_MultipleRankLevelInfos_ | |||
| 859 | 860 | ||
| 860 | MockTopoPathAndBuild(BuildEmptyTopo); | 861 | MockTopoPathAndBuild(BuildEmptyTopo); |
| 861 | 862 | ||
| 862 | - // When & Then: iterate all level infos, all graphs nullptr, no throw | 863 | + // When & Then: all unmatched ports are ignored |
| 863 | EXPECT_NO_THROW(rankInfoDetectClient_->HostListenPortDetect(rankInfo)); | 864 | EXPECT_NO_THROW(rankInfoDetectClient_->HostListenPortDetect(rankInfo)); |
| 864 | EXPECT_EQ(rankInfo.hostPort, DEFAULT_VALUE_TCPPORT); | 865 | EXPECT_EQ(rankInfo.hostPort, DEFAULT_VALUE_TCPPORT); |
| 865 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 | 866 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 |
| @@ -867,22 +868,22 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_MultipleRankLevelInfos_ | |||
| 867 | 868 | ||
| 868 | TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_RdmaLinkEmptyRankAddrs_Expect_Continue) | 869 | TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_RdmaLinkEmptyRankAddrs_Expect_Continue) |
| 869 | { | 870 | { |
| 870 | - // Given: host RDMA topology exists at netLayer=3, but rankAddrs is empty | 871 | + // Given: the physical topology has a HOST+ROCE link, but rankAddrs is empty |
| 871 | NewRankInfo rankInfo; | 872 | NewRankInfo rankInfo; |
| 872 | rankInfo.rankId = 0; | 873 | rankInfo.rankId = 0; |
| 873 | rankInfo.deviceId = 0; | 874 | rankInfo.deviceId = 0; |
| 874 | rankInfo.localId = 0; | 875 | rankInfo.localId = 0; |
| 875 | 876 | ||
| 876 | RankLevelInfo levelInfo; | 877 | RankLevelInfo levelInfo; |
| 877 | - levelInfo.netLayer = 3; // HOST+ROCE link at netLayer=3 | 878 | + levelInfo.netLayer = 3; |
| 878 | - // rankAddrs left EMPTY — triggers rankLevelInfo.rankAddrs.empty() check | 879 | + // rankAddrs is left empty, so no physical port can be matched |
| 879 | rankInfo.rankLevelInfos.push_back(levelInfo); | 880 | rankInfo.rankLevelInfos.push_back(levelInfo); |
| 880 | 881 | ||
| 881 | MOCKER(HrtGetDevice).stubs().will(returnValue(0)); | 882 | MOCKER(HrtGetDevice).stubs().will(returnValue(0)); |
| 882 | 883 | ||
| 883 | MockTopoPathAndBuild(BuildHostRdmaTopo); | 884 | MockTopoPathAndBuild(BuildHostRdmaTopo); |
| 884 | 885 | ||
| 885 | - // When & Then: ROCE → RDMA but rankAddrs.empty() → skip, hostPort unchanged | 886 | + // When & Then: the HOST+RDMA link is ignored and hostPort remains unchanged |
| 886 | PhyTopo::GetInstance()->Clear(); | 887 | PhyTopo::GetInstance()->Clear(); |
| 887 | EXPECT_NO_THROW(rankInfoDetectClient_->HostListenPortDetect(rankInfo)); | 888 | EXPECT_NO_THROW(rankInfoDetectClient_->HostListenPortDetect(rankInfo)); |
| 888 | EXPECT_EQ(rankInfo.hostPort, DEFAULT_VALUE_TCPPORT); | 889 | EXPECT_EQ(rankInfo.hostPort, DEFAULT_VALUE_TCPPORT); |
| @@ -892,7 +893,7 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_RdmaLinkEmptyRankAddrs_ | |||
| 892 | // basePort configured, portRange empty → listenPort = basePort + devPhyId | 893 | // basePort configured, portRange empty → listenPort = basePort + devPhyId |
| 893 | TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_BasePort_Expect_HostPortSet) | 894 | TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_BasePort_Expect_HostPortSet) |
| 894 | { | 895 | { |
| 895 | - // Given: HOST+ROCE link at netLayer=3, basePort configured | 896 | + // Given: a matching HOST+ROCE physical port and a configured basePort |
| 896 | EnvHostNicConfig fakeConfig; | 897 | EnvHostNicConfig fakeConfig; |
| 897 | fakeConfig.hcclHostSocketPortRange = CfgField<std::vector<SocketPortRange>>{ | 898 | fakeConfig.hcclHostSocketPortRange = CfgField<std::vector<SocketPortRange>>{ |
| 898 | "HCCL_HOST_SOCKET_PORT_RANGE", {}, [](const std::string& s) -> std::vector<SocketPortRange> { | 899 | "HCCL_HOST_SOCKET_PORT_RANGE", {}, [](const std::string& s) -> std::vector<SocketPortRange> { |
| @@ -911,8 +912,9 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_BasePort_Expect_HostPor | |||
| 911 | 912 | ||
| 912 | AddressInfo addrInfo; | 913 | AddressInfo addrInfo; |
| 913 | addrInfo.addr = IpAddress("192.168.1.1"); | 914 | addrInfo.addr = IpAddress("192.168.1.1"); |
| 915 | + addrInfo.ports.insert("host0"); | ||
| 914 | RankLevelInfo levelInfo; | 916 | RankLevelInfo levelInfo; |
| 915 | - levelInfo.netLayer = 3; // HOST+ROCE link at netLayer=3 | 917 | + levelInfo.netLayer = 3; |
| 916 | levelInfo.rankAddrs.push_back(addrInfo); | 918 | levelInfo.rankAddrs.push_back(addrInfo); |
| 917 | rankInfo.rankLevelInfos.push_back(levelInfo); | 919 | rankInfo.rankLevelInfos.push_back(levelInfo); |
| 918 | 920 | ||
| @@ -932,10 +934,9 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_BasePort_Expect_HostPor | |||
| 932 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 | 934 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 |
| 933 | } | 935 | } |
| 934 | 936 | ||
| 935 | -TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_NoHostLink_Expect_HostPortUnchanged) | 937 | +TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_DevicePortOnly_Expect_HostPortUnchanged) |
| 936 | { | 938 | { |
| 937 | - // Given: graph exists at netLayer=1, but links are DEVICE position instead of HOST | 939 | + // Given: the rank declares only a DEVICE physical port, not the HOST+RDMA port |
| 938 | - // This tests the path where graph has edges but none match HOST position | ||
| 939 | NewRankInfo rankInfo; | 940 | NewRankInfo rankInfo; |
| 940 | rankInfo.rankId = 0; | 941 | rankInfo.rankId = 0; |
| 941 | rankInfo.deviceId = 0; | 942 | rankInfo.deviceId = 0; |
| @@ -944,7 +945,8 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_NoHostLink_Expect_HostP | |||
| 944 | AddressInfo addrInfo; | 945 | AddressInfo addrInfo; |
| 945 | addrInfo.addr = IpAddress("192.168.1.1"); | 946 | addrInfo.addr = IpAddress("192.168.1.1"); |
| 946 | RankLevelInfo levelInfo; | 947 | RankLevelInfo levelInfo; |
| 947 | - levelInfo.netLayer = 1; // netLayer=1 has DEV links, not HOST | 948 | + addrInfo.ports.insert("0/0"); |
| 949 | + levelInfo.netLayer = 1; | ||
| 948 | levelInfo.rankAddrs.push_back(addrInfo); | 950 | levelInfo.rankAddrs.push_back(addrInfo); |
| 949 | rankInfo.rankLevelInfos.push_back(levelInfo); | 951 | rankInfo.rankLevelInfos.push_back(levelInfo); |
| 950 | 952 | ||
| @@ -952,11 +954,11 @@ TEST_F(RankInfoDetectClientTest, Ut_HostListenPortDetect_NoHostLink_Expect_HostP | |||
| 952 | 954 | ||
| 953 | MockTopoPathAndBuild(BuildHostRdmaTopo); | 955 | MockTopoPathAndBuild(BuildHostRdmaTopo); |
| 954 | 956 | ||
| 955 | - // When: netLayer=1 graph exists but has no HOST position links | 957 | + // When: the unified graph contains both DEVICE and HOST links |
| 956 | PhyTopo::GetInstance()->Clear(); | 958 | PhyTopo::GetInstance()->Clear(); |
| 957 | EXPECT_NO_THROW(rankInfoDetectClient_->HostListenPortDetect(rankInfo)); | 959 | EXPECT_NO_THROW(rankInfoDetectClient_->HostListenPortDetect(rankInfo)); |
| 958 | 960 | ||
| 959 | - // Then: hostPort should remain at default since no HOST RDMA link found | 961 | + // Then: hostPort remains unchanged because only the DEVICE port matches |
| 960 | EXPECT_EQ(rankInfo.hostPort, DEFAULT_VALUE_TCPPORT); | 962 | EXPECT_EQ(rankInfo.hostPort, DEFAULT_VALUE_TCPPORT); |
| 961 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 | 963 | PhyTopo::GetInstance()->Clear(); // 清理上一次测试的拓扑状态 |
| 962 | } | 964 | } |
| @@ -267,6 +267,16 @@ TEST_F(HcclRankGraphTest, Ut_HcclRankGraphGetLinks_When_ValidParam_Expect_Return | |||
| 267 | EXPECT_EQ(ret, HCCL_SUCCESS); | 267 | EXPECT_EQ(ret, HCCL_SUCCESS); |
| 268 | EXPECT_EQ(linkNum, 1); | 268 | EXPECT_EQ(linkNum, 1); |
| 269 | EXPECT_EQ(links[0].linkAttr.hop, 1); | 269 | EXPECT_EQ(links[0].linkAttr.hop, 1); |
| 270 | + u32 srcNetLayer = UINT32_MAX; | ||
| 271 | + u32 srcTopoInstId = UINT32_MAX; | ||
| 272 | + u32 dstNetLayer = UINT32_MAX; | ||
| 273 | + u32 dstTopoInstId = UINT32_MAX; | ||
| 274 | + EXPECT_TRUE(Hccl::GetEndpointTopoInfo(links[0].srcEndpointDesc, srcNetLayer, srcTopoInstId)); | ||
| 275 | + EXPECT_EQ(srcNetLayer, netLayer); | ||
| 276 | + EXPECT_EQ(srcTopoInstId, 0); | ||
| 277 | + EXPECT_TRUE(Hccl::GetEndpointTopoInfo(links[0].dstEndpointDesc, dstNetLayer, dstTopoInstId)); | ||
| 278 | + EXPECT_EQ(dstNetLayer, netLayer); | ||
| 279 | + EXPECT_EQ(dstTopoInstId, 0); | ||
| 270 | } | 280 | } |
| 271 | 281 | ||
| 272 | TEST_F(HcclRankGraphTest, Ut_HcclRankGraphGetLinks_When_Param_Is_InVaild_Expect_Return_Error) | 282 | TEST_F(HcclRankGraphTest, Ut_HcclRankGraphGetLinks_When_Param_Is_InVaild_Expect_Return_Error) |


🟡 Medium Priority
changed line:
detour_service.cc第 105-110 行,旧代码THROW<InvalidParamsException>在 P2P 端口数 != 1 时立即失败;新代码改为HCCL_WARNING + continue静默跳过该候选。affected behavior/contract:原先 P2P 绕路候选端口数不为 1 被视为严重配置错误并终止流程;现在该候选被静默丢弃,流程继续。
failure mode:当 topo.json / RankTable 配置出现异常导致某条 P2P 边端口数不为 1 时,原先会立即暴露(进程报错退出),现会被静默跳过。如果所有候选均被跳过,绕路链路将完全不生效,而进程不会报任何错误,导致在需要绕路的故障场景下集合通信失败或性能严重降级,排查极为困难。
suggested fix:将
HCCL_WARNING保留但额外增加计数器,在循环结束后若所有候选均被跳过(即实际添加的绕路 link 为 0),应输出HCCL_ERROR或抛出异常,确保异常情况不被完全淹没。建议:添加计数器跟踪被跳过的候选数量;循环结束后若有效绕路 link 数为 0 但至少有一个候选被跳过,应记录 HCCL_ERROR 或抛出异常。