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 =
19 : (unordered_map<string, LinkProtocol>{{"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 : {"UBG", LinkProtocol::UBG}
28 : });
29 :
30 : const unordered_map<std::string, TopoType> EdgeInfo::strToTopoType =
31 : (unordered_map<string, TopoType>{{"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,
47 : netLayer = GetJsonPropertyUInt(edgeInfoJson, "net_layer");
48 : );
49 149 : if (netLayer > MAX_VALUE_LEVEL) {
50 2 : THROW<InvalidParamsException>(StringFormat(
51 : "[EdgeInfo::%s] netLayer value[%u] is out of range[0, %u].", __func__, netLayer, MAX_VALUE_LEVEL));
52 : }
53 :
54 148 : DeserializeProtocol(edgeInfoJson);
55 :
56 146 : if (edgeInfoJson.contains("topo_type")) {
57 86 : std::string topoTypeStr;
58 86 : std::string msgtopoType = "[EdgeInfo::Deserialize] error occurs when parser object of propName \"topo_type\"";
59 86 : TRY_CATCH_THROW(InvalidParamsException, msgtopoType, topoTypeStr = GetJsonProperty(edgeInfoJson, "topo_type"););
60 88 : topoType = GetTopoType(topoTypeStr);
61 88 : } else {
62 172 : HCCL_WARNING("[EdgeInfo::%s] topo_type not found, [default]topo_type=TopoType::CLOS", __func__);
63 60 : topoType = TopoType::CLOS; // topo_type字段不存在时,取默认值CLOS
64 : }
65 :
66 144 : std::string msgtopoInstIdType = "[EdgeInfo::Deserialize] error occurs when parser object of propName \"topo_instance_id\"";
67 144 : if (edgeInfoJson.contains("topo_instance_id")) {
68 113 : TRY_CATCH_THROW(InvalidParamsException, msgtopoInstIdType,
69 : topoInstId = GetJsonPropertyUInt(edgeInfoJson, "topo_instance_id");
70 : );
71 : } else {
72 88 : HCCL_WARNING("[EdgeInfo::%s] topo_instance_id not found, [default]topo_instance_id=0", __func__);
73 32 : topoInstId = 0;
74 : }
75 :
76 : // 解析localA 和 localB
77 143 : DeserializeEndpoint(edgeInfoJson);
78 157 : }
79 :
80 148 : void EdgeInfo::DeserializeProtocol(const nlohmann::json &edgeInfoJson)
81 : {
82 148 : nlohmann::json jsonProtocols;
83 148 : std::string msgProtocols = "[EdgeInfo::DeserializeProtocol] error occurs when parser object of propName \"protocols\"";
84 148 : TRY_CATCH_THROW(InvalidParamsException, msgProtocols, 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 143 : std::string msglinkType = "[EdgeInfo::DeserializeEndpoint] error occurs when parser object of propName \"link_type\"";
104 143 : TRY_CATCH_THROW(InvalidParamsException, msglinkType,
105 : linkTypeStr = GetJsonProperty(edgeInfoJson, "link_type");
106 : );
107 144 : linkType = GetLinkType(linkTypeStr);
108 :
109 142 : std::string msgLocalA = "[EdgeInfo::DeserializeEndpoint] error occurs when parser object of propName \"local_a\"";
110 143 : TRY_CATCH_THROW(InvalidParamsException, msgLocalA,
111 : localA = GetJsonPropertyUInt(edgeInfoJson, "local_a");
112 : );
113 :
114 284 : DeserializePort(edgeInfoJson, "local_a_ports", localAPorts);
115 139 : if (localAPorts.empty()) {
116 0 : THROW<InvalidParamsException>("[EdgeInfo::%s] local_a_ports can not be empty", __func__);
117 : }
118 :
119 139 : if (linkType == LinkType::PEER2PEER) {
120 31 : std::string msgLocalB = "[EdgeInfo::DeserializeEndpoint] error occurs when parser object of propName \"local_b\"";
121 32 : TRY_CATCH_THROW(InvalidParamsException, msgLocalB,
122 : localB = GetJsonPropertyUInt(edgeInfoJson, "local_b");
123 : );
124 :
125 30 : if (localA == localB) { // localA 和 localB 不能是同一个点
126 1 : THROW<InvalidParamsException>("[EdgeInfo::%s] local_a and local_b can not be the same Endpoint id[%u].", __func__, localA);
127 : }
128 :
129 58 : DeserializePort(edgeInfoJson, "local_b_ports", localBPorts);
130 29 : if (localBPorts.empty()) {
131 0 : THROW<InvalidParamsException>("[EdgeInfo::%s] local_b_ports can not be empty when PEER2PEER", __func__);
132 : }
133 31 : } else {
134 108 : if (edgeInfoJson.contains("local_b") || edgeInfoJson.contains("local_b_ports")) {
135 1 : HCCL_WARNING("[EdgeInfo::%s] local_b and local_b_ports are not need when PEER2NET", __func__);
136 : }
137 : }
138 :
139 137 : if (edgeInfoJson.contains("position")) {
140 129 : string positionStr;
141 129 : std::string msgPosition = "[EdgeInfo::DeserializeEndpoint] error occurs when parser object of propName \"position\"";
142 129 : TRY_CATCH_THROW(InvalidParamsException, msgPosition, positionStr = GetJsonProperty(edgeInfoJson, "position"););
143 130 : position = GetAddrPosition(positionStr);
144 130 : } else {
145 24 : HCCL_WARNING("[EdgeInfo::%s] position not found, [default]position=DEVICE", __func__);
146 8 : position = AddrPosition::DEVICE;
147 : }
148 156 : }
149 :
150 170 : void EdgeInfo::DeserializePort(const nlohmann::json &edgeInfoJson, std::string propName, std::set<std::string> &ports)
151 : {
152 170 : nlohmann::json jsonPorts;
153 : std::string msgPort =
154 170 : StringFormat("[EdgeInfo::%s] error occurs when parser object of propName \"%s\"", __func__, propName.c_str());
155 170 : TRY_CATCH_THROW(InvalidParamsException, msgPort, GetJsonPropertyList(edgeInfoJson, propName.c_str(), jsonPorts));
156 170 : if (jsonPorts.empty() || jsonPorts.size() > MAX_PORTS_SIZE) {
157 1 : THROW<InvalidParamsException>("[EdgeInfo::%s] ports[%s].size=[%zu] out of range[1, %u]",
158 : __func__,
159 : propName.c_str(),
160 : jsonPorts.size(),
161 : MAX_PORTS_SIZE);
162 : }
163 549 : for (auto &portEle : jsonPorts) {
164 381 : string port = portEle.get<string>();
165 381 : if (!port.empty() && port.size() <= PORT_MAX_LENGTH) {
166 380 : if (ports.count(port) == 0) {
167 380 : ports.emplace(port);
168 : } else {
169 0 : HCCL_WARNING("[EdgeInfo::%s] Repeat port:[%s]", __func__, port.c_str());
170 : }
171 : } else {
172 1 : THROW<InvalidParamsException>("[EdgeInfo::%s] Invalid port[%s], length[%zu] out of range[1, %u]",
173 : __func__,
174 : port.c_str(),
175 : port.size(),
176 : PORT_MAX_LENGTH);
177 : }
178 381 : }
179 172 : }
180 :
181 2368 : bool EdgeInfo::operator==(const EdgeInfo &other) const
182 : {
183 4643 : return netLayer == other.netLayer && linkType == other.linkType && protocols == other.protocols &&
184 7012 : topoType == other.topoType && topoInstId == other.topoInstId && CompareEndpoints(other) &&
185 2369 : position == other.position;
186 : }
187 :
188 : // 比较EndpointA和B
189 2101 : bool EdgeInfo::CompareEndpoints(const EdgeInfo &other) const
190 : {
191 : // 无论什么情况,A=other.A && B=other.B时,可视为相同的连接关系
192 4209 : if (localA == other.localA &&
193 7 : localB == other.localB &&
194 2108 : localAPorts == other.localAPorts &&
195 0 : localBPorts == other.localBPorts) {
196 0 : return true;
197 : }
198 :
199 : // 当连接类型是PEER2PEER时,A=other.B && B=other.A时,可视为相同的连接关系
200 4202 : if (linkType == other.linkType &&
201 2101 : linkType == LinkType::PEER2PEER &&
202 29 : localA == other.localB &&
203 1 : localAPorts == other.localBPorts &&
204 4203 : localB == other.localA &&
205 1 : localBPorts == other.localAPorts) {
206 1 : return true;
207 : }
208 :
209 2100 : return false;
210 : }
211 :
212 147 : LinkProtocol EdgeInfo::GetLinkProtocol(string str) const
213 : {
214 147 : if (strToLinkProtocol.count(str) == 0) {
215 1 : THROW<InvalidParamsException>("[EdgeInfo::%s] string['%s'] is not type of LinkProtocol.", __func__, str.c_str());
216 : }
217 146 : return strToLinkProtocol.at(str);
218 : }
219 :
220 86 : TopoType EdgeInfo::GetTopoType(std::string topoTypeStr) const
221 : {
222 86 : if (topoTypeStr.empty()) {
223 0 : return TopoType::CLOS; // 不填写时,取默认值
224 : }
225 86 : if (strToTopoType.count(topoTypeStr) == 0) {
226 2 : THROW<InvalidParamsException>("[EdgeInfo::%s] string['%s'] is not type of TopoType.", __func__, topoTypeStr.c_str());
227 : }
228 84 : return strToTopoType.at(topoTypeStr);
229 : }
230 :
231 143 : LinkType EdgeInfo::GetLinkType(std::string linkTypeStr) const
232 : {
233 143 : if (strToLinkType.count(linkTypeStr) == 0) {
234 1 : THROW<InvalidParamsException>("[EdgeInfo::%s] string['%s'] is not type of LinkType.", __func__, linkTypeStr.c_str());
235 : }
236 142 : return strToLinkType.at(linkTypeStr);
237 : }
238 :
239 129 : AddrPosition EdgeInfo::GetAddrPosition(string str) const
240 : {
241 129 : if (str.empty()) {
242 0 : HCCL_WARNING("[EdgeInfo::%s] position is null, [default]position=DEVICE", __func__);
243 0 : return AddrPosition::DEVICE; // 默认取值为DEVICE
244 : }
245 129 : if (strToAddrPosition.count(str) == 0) {
246 1 : THROW<InvalidParamsException>(StringFormat("string ['%s'] is not type of AddrPosition.", str.c_str()));
247 : }
248 128 : return strToAddrPosition.at(str);
249 : }
250 :
251 10 : std::string EdgeInfo::Describe() const
252 : {
253 10 : stringstream protocolStr;
254 10 : protocolStr << "[";
255 20 : for (auto it = protocols.begin(); it != protocols.end(); ++it) {
256 10 : if (it != protocols.begin()) {
257 0 : protocolStr << ", ";
258 : }
259 10 : protocolStr << it->Describe();
260 : }
261 10 : protocolStr << "]";
262 :
263 10 : string localAPortsStr = DescribePorts(localAPorts);
264 10 : string localBPortsStr = DescribePorts(localBPorts);
265 :
266 10 : std::string description = "EdgeInfo{";
267 10 : description += StringFormat("netLayer=%u", netLayer);
268 10 : description += StringFormat("topoType=%s", topoType.Describe().c_str());
269 10 : description += StringFormat(", topoInstanceId=%u", topoInstId);
270 10 : description += StringFormat(", protocols=%s", protocolStr.str().c_str());
271 10 : description += StringFormat(", linkType=%s", linkType.Describe().c_str());
272 10 : description += StringFormat(", localA=%u", localA);
273 10 : description += StringFormat(", localAPortsStr=%s", localAPortsStr.c_str());
274 10 : description += StringFormat(", localB=%u", localB);
275 10 : description += StringFormat(", localBPortsStr=%s", localBPortsStr.c_str());
276 10 : description += StringFormat(", position=%s", position.Describe().c_str());
277 10 : description += "}";
278 10 : return description;
279 10 : }
280 :
281 20 : std::string EdgeInfo::DescribePorts(std::set<std::string> ports) const
282 : {
283 20 : stringstream portsStr;
284 20 : portsStr << "[";
285 38 : for (auto it = ports.begin(); it != ports.end(); ++it) {
286 18 : if (it != ports.begin()) {
287 2 : portsStr << ", ";
288 : }
289 18 : portsStr << *it;
290 : }
291 20 : portsStr << "]";
292 40 : return portsStr.str();
293 20 : }
294 :
295 143 : void EdgeInfo::GetBinStream(BinaryStream &binaryStream) const
296 : {
297 143 : binaryStream << netLayer << static_cast<u32>(linkType) << static_cast<u32>(topoType) << topoInstId;
298 143 : binaryStream << protocols.size();
299 286 : for (LinkProtocol protocol : protocols) {
300 143 : binaryStream << static_cast<u32>(protocol);
301 : }
302 :
303 143 : binaryStream << localA << localB;
304 :
305 143 : binaryStream << localAPorts.size();
306 519 : for (string port : localAPorts) {
307 376 : binaryStream << port;
308 376 : }
309 :
310 143 : binaryStream << localBPorts.size();
311 178 : for (string port : localBPorts) {
312 35 : binaryStream << port;
313 35 : }
314 :
315 143 : binaryStream << static_cast<u32>(position);
316 143 : }
317 :
318 73 : EdgeInfo::EdgeInfo(BinaryStream &binaryStream)
319 : {
320 73 : binaryStream >> netLayer;
321 : u32 linkTypeTmp;
322 73 : binaryStream >> linkTypeTmp;
323 73 : linkType = static_cast<LinkType::Value>(linkTypeTmp);
324 : u32 topoTypeTmp;
325 73 : binaryStream >> topoTypeTmp;
326 73 : topoType = static_cast<TopoType::Value>(topoTypeTmp);
327 73 : binaryStream >> topoInstId;
328 : size_t protocolSize;
329 73 : binaryStream >> protocolSize;
330 73 : protocols.clear();
331 146 : for (size_t i = 0; i < protocolSize; i++) {
332 : u32 protocolTmp;
333 73 : binaryStream >> protocolTmp;
334 73 : LinkProtocol protocol = static_cast<LinkProtocol::Value>(protocolTmp);
335 73 : protocols.emplace(protocol);
336 : }
337 :
338 73 : binaryStream >> localA >> localB;
339 :
340 : size_t localAPortsSize;
341 73 : binaryStream >> localAPortsSize;
342 73 : localAPorts.clear();
343 339 : for (size_t i = 0; i < localAPortsSize; i++) {
344 266 : string port;
345 266 : binaryStream >> port;
346 266 : localAPorts.emplace(port);
347 266 : }
348 :
349 : size_t localBPortsSize;
350 73 : binaryStream >> localBPortsSize;
351 73 : localBPorts.clear();
352 78 : for (size_t i = 0; i < localBPortsSize; i++) {
353 5 : string port;
354 5 : binaryStream >> port;
355 5 : localBPorts.emplace(port);
356 5 : }
357 :
358 : u32 positionTmp;
359 73 : binaryStream >> positionTmp;
360 73 : position = static_cast<AddrPosition::Value>(positionTmp);
361 73 : }
362 :
363 : } // namespace Hccl
|