Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "edge_info.h"
12 : #include "json_parser.h"
13 : #include "invalid_params_exception.h"
14 : #include "exception_util.h"
15 :
16 : namespace Hccl {
17 :
18 : const unordered_map<string, LinkProtocol> EdgeInfo::strToLinkProtocol = (unordered_map<string, LinkProtocol>{
19 : {"UB_CTP", LinkProtocol::UB_CTP},
20 : {"UB_TP", LinkProtocol::UB_TP},
21 : {"ROCE", LinkProtocol::ROCE},
22 : {"HCCS", LinkProtocol::HCCS},
23 : {"PCIE", LinkProtocol::PCIE},
24 : {"TCP", LinkProtocol::TCP},
25 : {"UB_MEM", LinkProtocol::UB_MEM},
26 : {"UBOE", LinkProtocol::UBOE},
27 : {"UB_RTP", LinkProtocol::UB_RTP},
28 : {"UBG", LinkProtocol::UB_RTP}});
29 :
30 : const unordered_map<std::string, TopoType> EdgeInfo::strToTopoType = (unordered_map<string, TopoType>{
31 : {"CLOS", TopoType::CLOS},
32 : {"1DMESH", TopoType::MESH_1D},
33 : {"2DMESH", TopoType::MESH_2D},
34 : {"A3_SERVER", TopoType::A3_SERVER},
35 : {"A2_AX_SERVER", TopoType::A2_AX_SERVER}});
36 :
37 : const unordered_map<string, LinkType> EdgeInfo::strToLinkType
38 : = (unordered_map<string, LinkType>{{"PEER2PEER", LinkType::PEER2PEER}, {"PEER2NET", LinkType::PEER2NET}});
39 :
40 : const unordered_map<string, AddrPosition> EdgeInfo::strToAddrPosition
41 : = (unordered_map<string, AddrPosition>{{"DEVICE", AddrPosition::DEVICE}, {"HOST", AddrPosition::HOST}});
42 :
43 149 : void EdgeInfo::Deserialize(const nlohmann::json& edgeInfoJson)
44 : {
45 149 : std::string msgNetLayer = "[EdgeInfo::Deserialize] error occurs when parser object of propName \"net_layer\"";
46 149 : TRY_CATCH_THROW(InvalidParamsException, msgNetLayer, netLayer = GetJsonPropertyUInt(edgeInfoJson, "net_layer"););
47 149 : if (netLayer > MAX_VALUE_LEVEL) {
48 2 : THROW<InvalidParamsException>(StringFormat(
49 : "[EdgeInfo::%s] netLayer value[%u] is out of range[0, %u].", __func__, netLayer, MAX_VALUE_LEVEL));
50 : }
51 :
52 148 : DeserializeProtocol(edgeInfoJson);
53 :
54 146 : if (edgeInfoJson.contains("topo_type")) {
55 86 : std::string topoTypeStr;
56 86 : std::string msgtopoType = "[EdgeInfo::Deserialize] error occurs when parser object of propName \"topo_type\"";
57 86 : TRY_CATCH_THROW(InvalidParamsException, msgtopoType, topoTypeStr = GetJsonProperty(edgeInfoJson, "topo_type"););
58 88 : topoType = GetTopoType(topoTypeStr);
59 88 : } else {
60 172 : HCCL_WARNING("[EdgeInfo::%s] topo_type not found, [default]topo_type=TopoType::CLOS", __func__);
61 60 : topoType = TopoType::CLOS; // topo_type字段不存在时,取默认值CLOS
62 : }
63 :
64 : std::string msgtopoInstIdType
65 144 : = "[EdgeInfo::Deserialize] error occurs when parser object of propName \"topo_instance_id\"";
66 144 : if (edgeInfoJson.contains("topo_instance_id")) {
67 113 : TRY_CATCH_THROW(InvalidParamsException, msgtopoInstIdType,
68 : topoInstId = GetJsonPropertyUInt(edgeInfoJson, "topo_instance_id"););
69 : } else {
70 88 : HCCL_WARNING("[EdgeInfo::%s] topo_instance_id not found, [default]topo_instance_id=0", __func__);
71 32 : topoInstId = 0;
72 : }
73 :
74 : // 解析localA 和 localB
75 143 : DeserializeEndpoint(edgeInfoJson);
76 157 : }
77 :
78 148 : void EdgeInfo::DeserializeProtocol(const nlohmann::json& edgeInfoJson)
79 : {
80 148 : nlohmann::json jsonProtocols;
81 : std::string msgProtocols
82 148 : = "[EdgeInfo::DeserializeProtocol] error occurs when parser object of propName \"protocols\"";
83 148 : TRY_CATCH_THROW(InvalidParamsException, msgProtocols,
84 : GetJsonPropertyList(edgeInfoJson, "protocols", jsonProtocols););
85 294 : for (auto& protocolEle : jsonProtocols) {
86 147 : auto protocolStr = protocolEle.get<std::string>();
87 148 : LinkProtocol protocol = GetLinkProtocol(protocolStr);
88 146 : if (protocols.count(protocol) == 0) {
89 146 : protocols.emplace(protocol);
90 : } else {
91 0 : HCCL_WARNING("[EdgeInfo::%s] repeat member[%s] in \"protocols\"", __func__, protocolStr.c_str());
92 : }
93 147 : }
94 :
95 147 : if (protocols.empty()) {
96 1 : THROW<InvalidParamsException>("[EdgeInfo::%s] \"protocols\" is empty", __func__);
97 : }
98 150 : }
99 :
100 143 : void EdgeInfo::DeserializeEndpoint(const nlohmann::json& edgeInfoJson)
101 : {
102 143 : std::string linkTypeStr;
103 : std::string msglinkType
104 143 : = "[EdgeInfo::DeserializeEndpoint] error occurs when parser object of propName \"link_type\"";
105 143 : TRY_CATCH_THROW(InvalidParamsException, msglinkType, linkTypeStr = GetJsonProperty(edgeInfoJson, "link_type"););
106 144 : linkType = GetLinkType(linkTypeStr);
107 :
108 142 : std::string msgLocalA = "[EdgeInfo::DeserializeEndpoint] error occurs when parser object of propName \"local_a\"";
109 143 : TRY_CATCH_THROW(InvalidParamsException, msgLocalA, localA = GetJsonPropertyUInt(edgeInfoJson, "local_a"););
110 :
111 284 : DeserializePort(edgeInfoJson, "local_a_ports", localAPorts);
112 139 : if (localAPorts.empty()) {
113 0 : THROW<InvalidParamsException>("[EdgeInfo::%s] local_a_ports can not be empty", __func__);
114 : }
115 :
116 139 : if (linkType == LinkType::PEER2PEER) {
117 : std::string msgLocalB
118 31 : = "[EdgeInfo::DeserializeEndpoint] error occurs when parser object of propName \"local_b\"";
119 32 : TRY_CATCH_THROW(InvalidParamsException, msgLocalB, localB = GetJsonPropertyUInt(edgeInfoJson, "local_b"););
120 :
121 30 : if (localA == localB) { // localA 和 localB 不能是同一个点
122 1 : THROW<InvalidParamsException>(
123 : "[EdgeInfo::%s] local_a and local_b can not be the same Endpoint id[%u].", __func__, localA);
124 : }
125 :
126 58 : DeserializePort(edgeInfoJson, "local_b_ports", localBPorts);
127 29 : if (localBPorts.empty()) {
128 0 : THROW<InvalidParamsException>("[EdgeInfo::%s] local_b_ports can not be empty when PEER2PEER", __func__);
129 : }
130 31 : } else {
131 108 : if (edgeInfoJson.contains("local_b") || edgeInfoJson.contains("local_b_ports")) {
132 1 : HCCL_WARNING("[EdgeInfo::%s] local_b and local_b_ports are not need when PEER2NET", __func__);
133 : }
134 : }
135 :
136 137 : if (edgeInfoJson.contains("position")) {
137 129 : string positionStr;
138 : std::string msgPosition
139 129 : = "[EdgeInfo::DeserializeEndpoint] error occurs when parser object of propName \"position\"";
140 129 : TRY_CATCH_THROW(InvalidParamsException, msgPosition, positionStr = GetJsonProperty(edgeInfoJson, "position"););
141 130 : position = GetAddrPosition(positionStr);
142 130 : } else {
143 24 : HCCL_WARNING("[EdgeInfo::%s] position not found, [default]position=DEVICE", __func__);
144 8 : position = AddrPosition::DEVICE;
145 : }
146 156 : }
147 :
148 170 : void EdgeInfo::DeserializePort(const nlohmann::json& edgeInfoJson, std::string propName, std::set<std::string>& ports)
149 : {
150 170 : nlohmann::json jsonPorts;
151 : std::string msgPort
152 170 : = StringFormat("[EdgeInfo::%s] error occurs when parser object of propName \"%s\"", __func__, propName.c_str());
153 170 : TRY_CATCH_THROW(InvalidParamsException, msgPort, GetJsonPropertyList(edgeInfoJson, propName.c_str(), jsonPorts));
154 170 : if (jsonPorts.empty() || jsonPorts.size() > MAX_PORTS_SIZE) {
155 1 : THROW<InvalidParamsException>(
156 : "[EdgeInfo::%s] ports[%s].size=[%zu] out of range[1, %u]", __func__, propName.c_str(), jsonPorts.size(),
157 : MAX_PORTS_SIZE);
158 : }
159 549 : for (auto& portEle : jsonPorts) {
160 381 : string port = portEle.get<string>();
161 381 : if (!port.empty() && port.size() <= PORT_MAX_LENGTH) {
162 380 : if (ports.count(port) == 0) {
163 380 : ports.emplace(port);
164 : } else {
165 0 : HCCL_WARNING("[EdgeInfo::%s] Repeat port:[%s]", __func__, port.c_str());
166 : }
167 : } else {
168 1 : THROW<InvalidParamsException>(
169 : "[EdgeInfo::%s] Invalid port[%s], length[%zu] out of range[1, %u]", __func__, port.c_str(), port.size(),
170 : PORT_MAX_LENGTH);
171 : }
172 381 : }
173 172 : }
174 :
175 2368 : bool EdgeInfo::operator==(const EdgeInfo& other) const
176 : {
177 2368 : return netLayer == other.netLayer && linkType == other.linkType && protocols == other.protocols
178 2275 : && topoType == other.topoType && topoInstId == other.topoInstId && CompareEndpoints(other)
179 4736 : && position == other.position;
180 : }
181 :
182 : // 比较EndpointA和B
183 2101 : bool EdgeInfo::CompareEndpoints(const EdgeInfo& other) const
184 : {
185 : // 无论什么情况,A=other.A && B=other.B时,可视为相同的连接关系
186 7 : if (localA == other.localA && localB == other.localB && localAPorts == other.localAPorts
187 2108 : && localBPorts == other.localBPorts) {
188 0 : return true;
189 : }
190 :
191 : // 当连接类型是PEER2PEER时,A=other.B && B=other.A时,可视为相同的连接关系
192 4202 : if (linkType == other.linkType && linkType == LinkType::PEER2PEER && localA == other.localB
193 4202 : && localAPorts == other.localBPorts && localB == other.localA && localBPorts == other.localAPorts) {
194 1 : return true;
195 : }
196 :
197 2100 : return false;
198 : }
199 :
200 149 : LinkProtocol EdgeInfo::GetLinkProtocol(string str) const
201 : {
202 149 : if (strToLinkProtocol.count(str) == 0) {
203 1 : THROW<InvalidParamsException>(
204 : "[EdgeInfo::%s] string['%s'] is not type of LinkProtocol.", __func__, str.c_str());
205 : }
206 148 : return strToLinkProtocol.at(str);
207 : }
208 :
209 86 : TopoType EdgeInfo::GetTopoType(std::string topoTypeStr) const
210 : {
211 86 : if (topoTypeStr.empty()) {
212 0 : return TopoType::CLOS; // 不填写时,取默认值
213 : }
214 86 : if (strToTopoType.count(topoTypeStr) == 0) {
215 2 : THROW<InvalidParamsException>(
216 : "[EdgeInfo::%s] string['%s'] is not type of TopoType.", __func__, topoTypeStr.c_str());
217 : }
218 84 : return strToTopoType.at(topoTypeStr);
219 : }
220 :
221 143 : LinkType EdgeInfo::GetLinkType(std::string linkTypeStr) const
222 : {
223 143 : if (strToLinkType.count(linkTypeStr) == 0) {
224 1 : THROW<InvalidParamsException>(
225 : "[EdgeInfo::%s] string['%s'] is not type of LinkType.", __func__, linkTypeStr.c_str());
226 : }
227 142 : return strToLinkType.at(linkTypeStr);
228 : }
229 :
230 129 : AddrPosition EdgeInfo::GetAddrPosition(string str) const
231 : {
232 129 : if (str.empty()) {
233 0 : HCCL_WARNING("[EdgeInfo::%s] position is null, [default]position=DEVICE", __func__);
234 0 : return AddrPosition::DEVICE; // 默认取值为DEVICE
235 : }
236 129 : if (strToAddrPosition.count(str) == 0) {
237 1 : THROW<InvalidParamsException>(StringFormat("string ['%s'] is not type of AddrPosition.", str.c_str()));
238 : }
239 128 : return strToAddrPosition.at(str);
240 : }
241 :
242 10 : std::string EdgeInfo::Describe() const
243 : {
244 10 : stringstream protocolStr;
245 10 : protocolStr << "[";
246 20 : for (auto it = protocols.begin(); it != protocols.end(); ++it) {
247 10 : if (it != protocols.begin()) {
248 0 : protocolStr << ", ";
249 : }
250 10 : protocolStr << it->Describe();
251 : }
252 10 : protocolStr << "]";
253 :
254 10 : string localAPortsStr = DescribePorts(localAPorts);
255 10 : string localBPortsStr = DescribePorts(localBPorts);
256 :
257 10 : std::string description = "EdgeInfo{";
258 10 : description += StringFormat("netLayer=%u", netLayer);
259 10 : description += StringFormat("topoType=%s", topoType.Describe().c_str());
260 10 : description += StringFormat(", topoInstanceId=%u", topoInstId);
261 10 : description += StringFormat(", protocols=%s", protocolStr.str().c_str());
262 10 : description += StringFormat(", linkType=%s", linkType.Describe().c_str());
263 10 : description += StringFormat(", localA=%u", localA);
264 10 : description += StringFormat(", localAPortsStr=%s", localAPortsStr.c_str());
265 10 : description += StringFormat(", localB=%u", localB);
266 10 : description += StringFormat(", localBPortsStr=%s", localBPortsStr.c_str());
267 10 : description += StringFormat(", position=%s", position.Describe().c_str());
268 10 : description += "}";
269 10 : return description;
270 10 : }
271 :
272 20 : std::string EdgeInfo::DescribePorts(std::set<std::string> ports) const
273 : {
274 20 : stringstream portsStr;
275 20 : portsStr << "[";
276 38 : for (auto it = ports.begin(); it != ports.end(); ++it) {
277 18 : if (it != ports.begin()) {
278 2 : portsStr << ", ";
279 : }
280 18 : portsStr << *it;
281 : }
282 20 : portsStr << "]";
283 40 : return portsStr.str();
284 20 : }
285 :
286 143 : void EdgeInfo::GetBinStream(BinaryStream& binaryStream) const
287 : {
288 143 : binaryStream << netLayer << static_cast<u32>(linkType) << static_cast<u32>(topoType) << topoInstId;
289 143 : binaryStream << protocols.size();
290 286 : for (LinkProtocol protocol : protocols) {
291 143 : binaryStream << static_cast<u32>(protocol);
292 : }
293 :
294 143 : binaryStream << localA << localB;
295 :
296 143 : binaryStream << localAPorts.size();
297 519 : for (string port : localAPorts) {
298 376 : binaryStream << port;
299 376 : }
300 :
301 143 : binaryStream << localBPorts.size();
302 178 : for (string port : localBPorts) {
303 35 : binaryStream << port;
304 35 : }
305 :
306 143 : binaryStream << static_cast<u32>(position);
307 143 : }
308 :
309 73 : EdgeInfo::EdgeInfo(BinaryStream& binaryStream)
310 : {
311 73 : binaryStream >> netLayer;
312 : u32 linkTypeTmp;
313 73 : binaryStream >> linkTypeTmp;
314 73 : linkType = static_cast<LinkType::Value>(linkTypeTmp);
315 : u32 topoTypeTmp;
316 73 : binaryStream >> topoTypeTmp;
317 73 : topoType = static_cast<TopoType::Value>(topoTypeTmp);
318 73 : binaryStream >> topoInstId;
319 : size_t protocolSize;
320 73 : binaryStream >> protocolSize;
321 73 : protocols.clear();
322 146 : for (size_t i = 0; i < protocolSize; i++) {
323 : u32 protocolTmp;
324 73 : binaryStream >> protocolTmp;
325 73 : LinkProtocol protocol = static_cast<LinkProtocol::Value>(protocolTmp);
326 73 : protocols.emplace(protocol);
327 : }
328 :
329 73 : binaryStream >> localA >> localB;
330 :
331 : size_t localAPortsSize;
332 73 : binaryStream >> localAPortsSize;
333 73 : localAPorts.clear();
334 339 : for (size_t i = 0; i < localAPortsSize; i++) {
335 266 : string port;
336 266 : binaryStream >> port;
337 266 : localAPorts.emplace(port);
338 266 : }
339 :
340 : size_t localBPortsSize;
341 73 : binaryStream >> localBPortsSize;
342 73 : localBPorts.clear();
343 78 : for (size_t i = 0; i < localBPortsSize; i++) {
344 5 : string port;
345 5 : binaryStream >> port;
346 5 : localBPorts.emplace(port);
347 5 : }
348 :
349 : u32 positionTmp;
350 73 : binaryStream >> positionTmp;
351 73 : position = static_cast<AddrPosition::Value>(positionTmp);
352 73 : }
353 :
354 : } // namespace Hccl
|