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