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