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