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 "address_info.h"
12 :
13 : #include <sstream>
14 : #include <vector>
15 : #include <string>
16 : #include <unordered_map>
17 : #include "json_parser.h"
18 : #include "invalid_params_exception.h"
19 : #include "exception_util.h"
20 : #include "adapter_error_manager_pub.h"
21 :
22 : namespace Hccl {
23 : using namespace std;
24 :
25 : const unordered_map<string, AddrType> AddressInfo::strToAddrType
26 : = (unordered_map<string, AddrType>{{"EID", AddrType::EID}, {"IPV4", AddrType::IPV4}, {"IPV6", AddrType::IPV6}});
27 :
28 331 : void AddressInfo::Deserialize(const nlohmann::json& addressInfoJson)
29 : {
30 331 : std::string addrTypeStr;
31 331 : std::string msgAddrtype = "error occurs when parser object of propName \"addr_type\"";
32 331 : TRY_CATCH_THROW(InvalidParamsException, msgAddrtype, addrTypeStr = GetJsonProperty(addressInfoJson, "addr_type"););
33 :
34 331 : if (!IsStringInAddrType(addrTypeStr)) {
35 2 : THROW<InvalidParamsException>(StringFormat("[AddressInfo::%s] failed with Invalid addrType. ", __func__));
36 : }
37 330 : addrType = strToAddrType.at(addrTypeStr);
38 :
39 330 : std::string address;
40 330 : std::string msgAddr = "error occurs when parser object of propName \"addr\"";
41 330 : TRY_CATCH_THROW(InvalidParamsException, msgAddr, address = GetJsonProperty(addressInfoJson, "addr"););
42 :
43 330 : if (address.length() < MIN_VALUE_ADDR_LENGRH || address.length() > MAX_VALUE_ADDR_LENGRH) {
44 2 : if (address.empty()) {
45 34 : RPT_INPUT_ERR(
46 : true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
47 : std::vector<std::string>({"N/A", "addr", "addr is required and should not be empty"}));
48 : } else {
49 0 : RPT_INPUT_ERR(
50 : true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
51 : std::vector<std::string>({address, "addr", "A ip address"}));
52 : }
53 4 : THROW<InvalidParamsException>(StringFormat(
54 : "addr [%.*s] length is out of range [%u] to [%u]", MAX_DISPLAY_LEN, address.c_str(), MIN_VALUE_ADDR_LENGRH,
55 : MAX_VALUE_ADDR_LENGRH));
56 : }
57 :
58 824 : HCCL_INFO("[AddressInfo::%s] addrTypeStr is[%s]", __func__, addrTypeStr.c_str());
59 328 : if (addrTypeStr == "IPV4") {
60 323 : IPV4ToAddr(address);
61 9 : } else if (addrTypeStr == "IPV6") {
62 8 : IPV6ToAddr(address);
63 4 : } else if (addrTypeStr == "EID") {
64 6 : EidToAddr(address);
65 : }
66 : // 先解析主地址以确定 addrType,再使用同一类型校验可选的 backup_addr。
67 319 : const std::string msgBackupAddr = "deserialize backup_addr failed";
68 324 : TRY_CATCH_THROW(InvalidParamsException, msgBackupAddr, DeserializeBackupAddrs(addressInfoJson, addrTypeStr););
69 :
70 314 : planeId = addressInfoJson.value<std::string>("plane_id", "0");
71 314 : if (planeId.length() > MAX_VALUE_PLANEID) {
72 0 : THROW<InvalidParamsException>(StringFormat(
73 : "plane_id [%s] length is out of range [%u] to [%u]", planeId.c_str(), MIN_VALUE_PLANEID,
74 : MAX_VALUE_PLANEID));
75 : }
76 :
77 314 : nlohmann::json portsJsons;
78 314 : std::string msgPortlist = "error occurs when parser object of propName \"ports\"";
79 314 : TRY_CATCH_THROW(InvalidParamsException, msgPortlist, GetJsonPropertyList(addressInfoJson, "ports", portsJsons););
80 741 : for (auto& portsJson : portsJsons) {
81 428 : if (portsJson.get<std::string>().size() < MIN_VALUE_PORT_LENGTH
82 428 : || portsJson.get<std::string>().size() > MAX_VALUE_PORT_LENGTH) {
83 2 : THROW<InvalidParamsException>(StringFormat(
84 3 : "portsString [%u] length is out of range [%u] to [%u]", portsJson.get<std::string>().size(),
85 : MIN_VALUE_PORT_LENGTH, MAX_VALUE_PORT_LENGTH));
86 : }
87 427 : ports.emplace(portsJson);
88 : }
89 313 : if (ports.size() < MIN_VALUE_PORT || ports.size() > MAX_VALUE_PORT) {
90 2 : THROW<InvalidParamsException>(StringFormat(
91 : "ports [%u] length is out of range [%u] to [%u]", ports.size(), MIN_VALUE_PORT, MAX_VALUE_PORT));
92 : }
93 397 : }
94 :
95 75 : void AddressInfo::ParseAddrByType(const std::string& addrType, const std::string& address, IpAddress& ipAddress)
96 : {
97 75 : if (addrType == "IPV4") {
98 75 : CHK_PRT_THROW(
99 : !IpAddress::IsIPv4(address),
100 : HCCL_ERROR("[%s] invalid IPV4 backup_addr[%.*s].", __func__, MAX_DISPLAY_LEN, address.c_str()),
101 : InvalidParamsException, "invalid IPV4 backup_addr");
102 66 : ipAddress = IpAddress(address, AF_INET);
103 6 : } else if (addrType == "IPV6") {
104 5 : CHK_PRT_THROW(
105 : !IpAddress::IsIPv6(address),
106 : HCCL_ERROR("[%s] invalid IPV6 backup_addr[%.*s].", __func__, MAX_DISPLAY_LEN, address.c_str()),
107 : InvalidParamsException, "invalid IPV6 backup_addr");
108 5 : ipAddress = IpAddress(address, AF_INET6);
109 : } else {
110 1 : THROW<InvalidParamsException>(
111 2 : StringFormat("[%s] backup_addr does not support addrType[%s].", __func__, addrType.c_str()));
112 : }
113 71 : }
114 :
115 25 : void AddressInfo::ParseBackupAddrs(
116 : const nlohmann::json& backupAddrJson, const std::string& addrType, std::vector<IpAddress>& backupAddrs)
117 : {
118 25 : backupAddrs.clear();
119 29 : CHK_PRT_THROW(
120 : !backupAddrJson.is_array(), HCCL_ERROR("[%s] backup_addr should be an array.", __func__),
121 : InvalidParamsException, "backup_addr should be an array");
122 27 : CHK_PRT_THROW(
123 : backupAddrJson.size() > MAX_VALUE_BACKUP_ADDR_SIZE,
124 : HCCL_ERROR(
125 : "[%s] backup_addr size[%zu] exceeds max[%u].", __func__, backupAddrJson.size(), MAX_VALUE_BACKUP_ADDR_SIZE),
126 : InvalidParamsException, "backup_addr size exceeds max");
127 :
128 75 : for (const auto& backupAddr : backupAddrJson) {
129 63 : CHK_PRT_THROW(
130 : !backupAddr.is_string(), HCCL_ERROR("[%s] backup_addr element should be string.", __func__),
131 : InvalidParamsException, "backup_addr element should be string");
132 57 : const std::string backupAddrStr = backupAddr.get<std::string>();
133 57 : CHK_PRT_THROW(
134 : backupAddrStr.length() < MIN_VALUE_ADDR_LENGRH || backupAddrStr.length() > MAX_VALUE_ADDR_LENGRH,
135 : HCCL_ERROR(
136 : "[%s] backup_addr[%.*s] length is out of range [%u] to [%u].", __func__, MAX_DISPLAY_LEN,
137 : backupAddrStr.c_str(), MIN_VALUE_ADDR_LENGRH, MAX_VALUE_ADDR_LENGRH),
138 : InvalidParamsException,
139 : StringFormat(
140 : "[%s] backup_addr [%.*s] length is out of range [%u] to [%u]", __func__, MAX_DISPLAY_LEN,
141 : backupAddrStr.c_str(), MIN_VALUE_ADDR_LENGRH, MAX_VALUE_ADDR_LENGRH));
142 57 : IpAddress backupIpAddress;
143 57 : const std::string msgParseBackupAddr = "parse backup_addr failed";
144 60 : TRY_CATCH_THROW(InvalidParamsException, msgParseBackupAddr,
145 : ParseAddrByType(addrType, backupAddrStr, backupIpAddress););
146 54 : backupAddrs.emplace_back(backupIpAddress);
147 60 : }
148 16 : }
149 :
150 319 : void AddressInfo::DeserializeBackupAddrs(const nlohmann::json& addressInfoJson, const std::string& addrTypeStr)
151 : {
152 319 : backupAddrs.clear();
153 : // backup_addr 为可选字段,缺失时兼容未配置主备地址的 RankTable。
154 319 : if (!addressInfoJson.contains("backup_addr")) {
155 807 : HCCL_WARNING("[%s] backup_addr is not configured.", __func__);
156 311 : return;
157 : }
158 8 : ParseBackupAddrs(addressInfoJson.at("backup_addr"), addrTypeStr, backupAddrs);
159 : }
160 :
161 4 : void AddressInfo::EidToAddr(std::string address)
162 : {
163 4 : if (address.length() != URMA_EID_LEN * URMA_EID_NUM_TWO) {
164 1 : THROW<InvalidParamsException>(
165 3 : StringFormat("[AddressInfo::%s] failed with rankAddrs : error in length. ", __func__));
166 3 : } else if (!IpAddress::IsEID(address)) {
167 1 : THROW<InvalidParamsException>(
168 3 : StringFormat("[AddressInfo::%s] failed with rankAddrs : error in format. ", __func__));
169 : }
170 2 : Eid eid = IpAddress::StrToEID(address);
171 2 : IpAddress ipAddress0(eid);
172 2 : addr = ipAddress0;
173 2 : }
174 :
175 319 : void AddressInfo::IPV4ToAddr(std::string address)
176 : {
177 319 : s32 ipFamily = AF_INET;
178 :
179 319 : if (IpAddress::IsIPv4(address)) {
180 315 : ipFamily = AF_INET;
181 : } else {
182 8 : THROW<InvalidParamsException>(StringFormat("[AddressInfo::%s] failed with addrs is error. ", __func__));
183 : }
184 315 : IpAddress ipAddress0(address, ipFamily);
185 315 : addr = ipAddress0;
186 811 : HCCL_INFO("[AddressInfo::%s] IpAddress is[%s]", __func__, ipAddress0.Describe().c_str());
187 315 : }
188 :
189 5 : void AddressInfo::IPV6ToAddr(std::string address)
190 : {
191 5 : s32 ipFamily = AF_INET6;
192 :
193 5 : if (IpAddress::IsIPv6(address)) {
194 2 : ipFamily = AF_INET6;
195 : } else {
196 6 : THROW<InvalidParamsException>(StringFormat("[AddressInfo::%s] failed with addr is error. ", __func__));
197 : }
198 2 : IpAddress ipAddress0(address, ipFamily);
199 2 : addr = ipAddress0;
200 2 : }
201 :
202 1 : std::string AddressInfo::Describe() const
203 : {
204 : return StringFormat(
205 : "AddressInfo[addrType=%s, addr=%s, backupAddrSize=%u, planeId=%s, portsize=%u socketPort_=%u]",
206 3 : addrType.Describe().c_str(), addr.Describe().c_str(), static_cast<u32>(backupAddrs.size()), planeId.c_str(),
207 4 : static_cast<u32>(ports.size()), socketPort_);
208 : }
209 :
210 28 : AddressInfo::AddressInfo(BinaryStream& binStream)
211 : {
212 14 : IpAddress address(binStream);
213 14 : addr = address;
214 14 : u32 addrTypeInt{0};
215 14 : binStream >> addrTypeInt;
216 14 : addrType = static_cast<AddrType::Value>(addrTypeInt);
217 14 : size_t portsSize{0};
218 14 : binStream >> portsSize;
219 41 : for (u32 i = 0; i < portsSize; i++) {
220 27 : string port;
221 27 : binStream >> port;
222 27 : ports.emplace(port);
223 27 : }
224 14 : binStream >> planeId;
225 14 : binStream >> socketPort_;
226 14 : size_t backupAddrSize{0};
227 14 : binStream >> backupAddrSize;
228 16 : CHK_PRT_THROW(
229 : backupAddrSize > MAX_VALUE_BACKUP_ADDR_SIZE,
230 : HCCL_ERROR("[%s] backup_addr size[%zu] exceeds max[%u].", __func__, backupAddrSize, MAX_VALUE_BACKUP_ADDR_SIZE),
231 : InvalidParamsException, "backup_addr size exceeds limit");
232 16 : for (size_t i = 0; i < backupAddrSize; i++) {
233 3 : IpAddress backupAddr(binStream);
234 3 : backupAddrs.emplace_back(backupAddr);
235 : }
236 16 : }
237 :
238 114 : void AddressInfo::GetBinStream(BinaryStream& binStream) const
239 : {
240 114 : if (ports.size() == 0) {
241 0 : std::string msg = StringFormat("ports size is zero.");
242 0 : THROW<InvalidParamsException>(msg);
243 0 : }
244 114 : addr.GetBinStream(binStream);
245 114 : binStream << static_cast<u32>(addrType);
246 114 : binStream << ports.size();
247 283 : for (auto& it : ports) {
248 169 : binStream << it;
249 : }
250 114 : binStream << planeId;
251 114 : binStream << socketPort_;
252 114 : binStream << backupAddrs.size();
253 117 : for (const auto& backupAddr : backupAddrs) {
254 3 : backupAddr.GetBinStream(binStream);
255 : }
256 114 : }
257 :
258 : } // namespace Hccl
|