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 : #include "base_config.h"
11 : #include <fstream>
12 : #include <algorithm>
13 : #include <array>
14 : #include "log.h"
15 :
16 : namespace Hccl {
17 :
18 : // EnvHostNicConfig
19 :
20 16 : void EnvHostNicConfig::Parse()
21 : {
22 16 : hcclIfIp.Parse();
23 28 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_IF_IP set by %s to [%s]", hcclIfIp.GetSource(), GetControlIfIp().Describe().c_str());
24 :
25 16 : hcclIfBasePort.Parse();
26 28 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_IF_BASE_PORT set by %s to [%u]", hcclIfBasePort.GetSource(), GetIfBasePort());
27 :
28 16 : hcclSocketIfName.Parse();
29 28 : HCCL_RUN_INFO(
30 : "[HCCL_ENV] HCCL_SOCKET_IFNAME set by %s to [%s]", hcclSocketIfName.GetSource(),
31 : GetSocketIfName().configIfNameStr.c_str());
32 :
33 16 : whitelistDisable.Parse();
34 28 : HCCL_RUN_INFO(
35 : "[HCCL_ENV] HCCL_WHITELIST_DISABLE set by %s to [%d]", whitelistDisable.GetSource(), whitelistDisable.Get());
36 :
37 16 : if (!whitelistDisable.Get()) {
38 1 : hcclWhiteListFile.Parse();
39 3 : HCCL_RUN_INFO(
40 : "[HCCL_ENV] HCCL_WHITELIST_FILE set by %s to [%s]", hcclWhiteListFile.GetSource(),
41 : GetWhiteListFile().c_str());
42 : }
43 :
44 16 : hcclHostSocketPortRange.Parse();
45 16 : std::ostringstream hosrPortRangeOss;
46 17 : for (auto range : GetHostSocketPortRange()) {
47 1 : hosrPortRangeOss << "[" << range.min << ", " << range.max << "]";
48 : }
49 28 : HCCL_RUN_INFO(
50 : "[HCCL_ENV] HCCL_HOST_SOCKET_PORT_RANGE set by %s to %s", hcclHostSocketPortRange.GetSource(),
51 : hosrPortRangeOss.str().c_str());
52 :
53 16 : hcclDeviceSocketPortRange.Parse();
54 16 : std::ostringstream devicePortRangeOss;
55 16 : for (auto range : GetDeviceSocketPortRange()) {
56 0 : devicePortRangeOss << "[" << range.min << ", " << range.max << "]";
57 : }
58 28 : HCCL_RUN_INFO(
59 : "[HCCL_ENV] HCCL_NPU_SOCKET_PORT_RANGE set by %s to %s", hcclDeviceSocketPortRange.GetSource(),
60 : devicePortRangeOss.str().c_str());
61 16 : }
62 :
63 24 : const IpAddress& EnvHostNicConfig::GetControlIfIp() const { return hcclIfIp.Get(); }
64 :
65 51 : u32 EnvHostNicConfig::GetIfBasePort() const { return hcclIfBasePort.Get(); }
66 :
67 25 : const SocketIfName& EnvHostNicConfig::GetSocketIfName() const { return hcclSocketIfName.Get(); }
68 :
69 42 : bool EnvHostNicConfig::GetWhitelistDisable() const { return whitelistDisable.Get(); }
70 :
71 2 : const std::string& EnvHostNicConfig::GetWhiteListFile() const { return hcclWhiteListFile.Get(); }
72 :
73 54 : const std::vector<SocketPortRange>& EnvHostNicConfig::GetHostSocketPortRange() const
74 : {
75 54 : return hcclHostSocketPortRange.Get();
76 : }
77 :
78 18 : const std::vector<SocketPortRange>& EnvHostNicConfig::GetDeviceSocketPortRange() const
79 : {
80 18 : return hcclDeviceSocketPortRange.Get();
81 : }
82 :
83 : // EnvSocketConfig
84 :
85 16 : void EnvSocketConfig::Parse()
86 : {
87 16 : hcclSocketFamily.Parse();
88 28 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_SOCKET_FAMILY set by %s to [%d]", hcclSocketFamily.GetSource(), GetSocketFamily());
89 :
90 16 : linkTimeOut.Parse();
91 28 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_CONNECT_TIMEOUT set by %s to [%d]s", linkTimeOut.GetSource(), GetLinkTimeOut());
92 16 : }
93 :
94 23 : s32 EnvSocketConfig::GetSocketFamily() const { return hcclSocketFamily.Get(); }
95 :
96 66 : s32 EnvSocketConfig::GetLinkTimeOut() const { return linkTimeOut.Get(); }
97 :
98 : // EnvRtsConfig
99 :
100 16 : void EnvRtsConfig::Parse()
101 : {
102 16 : execTimeOut.Parse();
103 16 : aivExecTimeOut.Parse();
104 28 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_EXEC_TIMEOUT set by %s to [%u]s", execTimeOut.GetSource(), GetExecTimeOut());
105 16 : }
106 :
107 253 : u32 EnvRtsConfig::GetExecTimeOut() const { return execTimeOut.Get(); }
108 :
109 1 : double EnvRtsConfig::GetAivExecTimeOut() const { return aivExecTimeOut.Get(); }
110 :
111 : // EnvRdmaConfig
112 :
113 37 : void EnvRdmaConfig::Parse()
114 : {
115 37 : rdmaTrafficClass.Parse();
116 91 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_RDMA_TC set by %s to [%u]", rdmaTrafficClass.GetSource(), GetRdmaTrafficClass());
117 :
118 37 : rdmaServerLevel.Parse();
119 91 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_RDMA_SL set by %s to [%u]", rdmaServerLevel.GetSource(), GetRdmaServerLevel());
120 :
121 37 : rdmaTimeOut.Parse();
122 91 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_RDMA_TIMEOUT set by %s to [%u]", rdmaTimeOut.GetSource(), GetRdmaTimeOut());
123 :
124 37 : rdmaRetryCnt.Parse();
125 91 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_RDMA_RETRY_CNT set by %s to [%u]", rdmaRetryCnt.GetSource(), GetRdmaRetryCnt());
126 :
127 37 : uboeTimeOut.Parse();
128 88 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_UBOE_TIMEOUT set by %s to [%u]", uboeTimeOut.GetSource(), GetUboeTimeOut());
129 :
130 36 : ubTimeOut.Parse();
131 85 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_UB_TIMEOUT set by %s to [%u]", ubTimeOut.GetSource(), GetUbTimeOut());
132 :
133 35 : queueNum.Parse();
134 82 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_RDMA_QPS_PER_CONNECTION set by %s to [%u]", queueNum.GetSource(), GetRdmaQueueNum());
135 :
136 34 : multiQpThreshold.Parse();
137 79 : HCCL_RUN_INFO(
138 : "[HCCL_ENV] HCCL_MULTI_QP_THRESHOLD set by %s to [%u]B", multiQpThreshold.GetSource(),
139 : GetRdmaMultiQpThreshold());
140 :
141 33 : qpPortConfigPath.Parse();
142 73 : HCCL_RUN_INFO(
143 : "[HCCL_ENV] HCCL_RDMA_QP_PORT_CONFIG_PATH set by %s to [%s]", qpPortConfigPath.GetSource(),
144 : qpPortConfigPath.Get().c_str());
145 31 : ParseMultiQpSrcPortConfig();
146 31 : }
147 :
148 6 : HcclResult EnvRdmaConfig::OpenMultiQpConfigFile(std::ifstream& inFile)
149 : {
150 6 : std::string fileStr = qpPortConfigPath.Get() + "/MultiQpSrcPort.cfg";
151 6 : std::array<char, PATH_MAX> realFile{};
152 6 : if (realpath(fileStr.c_str(), realFile.data()) == nullptr) {
153 0 : HCCL_ERROR("[EnvRdmaConfig][OpenMultiQpConfigFile] config file path[%s] is invalid.", fileStr.c_str());
154 0 : return HCCL_E_PARA;
155 : }
156 :
157 6 : inFile.open(fileStr.c_str(), std::ifstream::in);
158 6 : if (!inFile) {
159 0 : HCCL_ERROR("[EnvRdmaConfig][OpenMultiQpConfigFile] open config file[%s] failed.", fileStr.c_str());
160 0 : return HCCL_E_PARA;
161 : }
162 18 : HCCL_INFO("[EnvRdmaConfig][OpenMultiQpConfigFile] open config file[%s] success.", fileStr.c_str());
163 6 : return HCCL_SUCCESS;
164 6 : }
165 :
166 6 : HcclResult EnvRdmaConfig::ParseConfigContent(std::ifstream& inFile, MultiQpSrcPortConfig& config)
167 : {
168 6 : config.configDirPath = qpPortConfigPath.Get();
169 6 : u32 lineCnt = 1;
170 6 : std::string line;
171 131079 : while (std::getline(inFile, line)) {
172 131076 : std::string lineAvator = line;
173 131076 : line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
174 131076 : line.erase(std::remove(line.begin(), line.end(), '\t'), line.end());
175 131076 : auto hashPos = line.find('#');
176 131076 : std::string lineInfo = (hashPos != std::string::npos) ? line.substr(0, hashPos) : line;
177 131076 : if (lineInfo.empty()) {
178 131070 : lineCnt++;
179 131070 : continue;
180 : }
181 :
182 6 : std::string ipPairKey, portPart;
183 6 : HcclResult ret = ParseLineToIpPairAndPortPart(lineInfo, lineCnt, lineAvator, ipPairKey, portPart);
184 6 : if (ret != HCCL_SUCCESS) {
185 1 : return ret;
186 : }
187 5 : std::vector<std::uint16_t> ports;
188 5 : ret = ParseSrcPortsFromPortPart(portPart, lineCnt, lineAvator, ports);
189 5 : if (ret != HCCL_SUCCESS) {
190 1 : return ret;
191 : }
192 4 : CHK_PRT_RET(
193 : config.ipPairToPorts.find(ipPairKey) != config.ipPairToPorts.end(),
194 : HCCL_ERROR(
195 : "[MulQpInfo][ParseSrcPortsFromString][line: %u] ip pair[%s] already exists.[%s]", lineCnt,
196 : ipPairKey.c_str(), lineAvator.c_str()),
197 : HCCL_E_PARA);
198 4 : config.ipPairToPorts[ipPairKey] = ports;
199 4 : if (lineCnt >= MultiQpSrcPortConfig::CONFIG_FILE_LINE_MAX) {
200 3 : HCCL_RUN_INFO("config file is too large, stop parsing at line %u.", lineCnt);
201 1 : break;
202 : }
203 3 : lineCnt++;
204 262157 : }
205 4 : return HCCL_SUCCESS;
206 6 : }
207 :
208 31 : void EnvRdmaConfig::ParseMultiQpSrcPortConfig()
209 : {
210 31 : if (!qpPortConfigPath.IsSetByEnvironment() || qpPortConfigPath.Get().empty()) {
211 25 : return;
212 : }
213 : try {
214 6 : std::ifstream inFile;
215 6 : CHK_PRT_THROW(
216 : OpenMultiQpConfigFile(inFile) != HCCL_SUCCESS,
217 : HCCL_ERROR("[EnvRdmaConfig][Parse] open multi qp src port config file failed."), InvalidParamsException,
218 : "open config file fail.");
219 :
220 6 : MultiQpSrcPortConfig config;
221 16 : CHK_PRT_THROW(
222 : ParseConfigContent(inFile, config) != HCCL_SUCCESS,
223 : HCCL_ERROR("[EnvRdmaConfig][Parse] parse multi qp src port config content failed."), InvalidParamsException,
224 : "parse config content fail.");
225 :
226 4 : inFile.close();
227 4 : multiQpSrcPortConfig_ = config;
228 4 : LogMultiQpSrcPortConfig();
229 10 : } catch (const HcclException& e) {
230 6 : HCCL_ERROR("[EnvRdmaConfig][Parse] LoadMultiQpSrcPortConfig failed: %s", e.what());
231 2 : } catch (const std::exception& e) {
232 0 : HCCL_ERROR("[EnvRdmaConfig][Parse] LoadMultiQpSrcPortConfig failed: %s", e.what());
233 0 : }
234 : }
235 :
236 6 : HcclResult EnvRdmaConfig::ParseLineToIpPairAndPortPart(
237 : const std::string& lineInfo, u32 lineCnt, const std::string& lineAvator, std::string& ipPairKey,
238 : std::string& portPart)
239 : {
240 6 : auto eqPos = lineInfo.find('=');
241 9 : CHK_PRT_RET(
242 : eqPos == std::string::npos || eqPos == 0 || eqPos == lineInfo.size() - 1,
243 : HCCL_ERROR(
244 : "[MulQpInfo][ParseSrcPortsFromString][line: %u]Expected format: "
245 : "'srcIP,dstIP=srcPort0,srcPort1,...'.[%s]",
246 : lineCnt, lineAvator.c_str()),
247 : HCCL_E_PARA);
248 5 : CHK_PRT_RET(
249 : lineInfo.find('=', eqPos + 1) != std::string::npos,
250 : HCCL_ERROR(
251 : "[MulQpInfo][ParseSrcPortsFromString][line: %u]Expected format: "
252 : "'srcIP,dstIP=srcPort0,srcPort1,...'.[%s]",
253 : lineCnt, lineAvator.c_str()),
254 : HCCL_E_PARA);
255 5 : std::string ipPart = lineInfo.substr(0, eqPos);
256 5 : portPart = lineInfo.substr(eqPos + 1);
257 :
258 5 : auto commaPos = ipPart.find(',');
259 5 : CHK_PRT_RET(
260 : commaPos == std::string::npos,
261 : HCCL_ERROR(
262 : "[MulQpInfo][ParseSrcPortsFromString][line: %u] IP pair format error, "
263 : "expected 'srcIP,dstIP'.[%s]",
264 : lineCnt, lineAvator.c_str()),
265 : HCCL_E_PARA);
266 5 : CHK_PRT_RET(
267 : ipPart.find(',', commaPos + 1) != std::string::npos,
268 : HCCL_ERROR(
269 : "[MulQpInfo][ParseSrcPortsFromString][line: %u] IP pair format error, "
270 : "expected 'srcIP,dstIP'.[%s]",
271 : lineCnt, lineAvator.c_str()),
272 : HCCL_E_PARA);
273 :
274 5 : IpAddress srcIpAddr, dstIpAddr;
275 : try {
276 5 : srcIpAddr = IpAddress(ipPart.substr(0, commaPos));
277 5 : dstIpAddr = IpAddress(ipPart.substr(commaPos + 1));
278 0 : } catch (const InvalidParamsException& e) {
279 0 : HCCL_ERROR(
280 : "[MulQpInfo][ParseSrcPortsFromString][line: %u] IP format error: %s.[%s]", lineCnt, e.what(),
281 : lineAvator.c_str());
282 0 : return HCCL_E_PARA;
283 0 : }
284 :
285 5 : ipPairKey = srcIpAddr.GetIpStr() + "," + dstIpAddr.GetIpStr();
286 5 : return HCCL_SUCCESS;
287 5 : }
288 :
289 5 : HcclResult EnvRdmaConfig::ParseSrcPortsFromPortPart(
290 : const std::string& portPart, u32 lineCnt, const std::string& lineAvator, std::vector<std::uint16_t>& ports)
291 : {
292 5 : std::size_t start = 0;
293 : while (true) {
294 69 : auto p = portPart.find(',', start);
295 69 : std::string token = (p != std::string::npos) ? portPart.substr(start, p - start) : portPart.substr(start);
296 :
297 69 : CHK_PRT_RET(
298 : token.empty(),
299 : HCCL_ERROR(
300 : "[MulQpInfo][ParseSrcPortsFromString][line: %u]src port[%s] is empty.[%s]", lineCnt, token.c_str(),
301 : lineAvator.c_str()),
302 : HCCL_E_PARA);
303 :
304 69 : unsigned long val = 0;
305 : try {
306 69 : std::size_t parsePos = 0;
307 69 : val = std::stoul(token, &parsePos, 0);
308 69 : if (parsePos != token.size()) {
309 0 : HCCL_ERROR(
310 : "[MulQpInfo][ParseSrcPortsFromString][line: %u] port[%s] is not a valid integer.[%s]", lineCnt,
311 : token.c_str(), lineAvator.c_str());
312 0 : return HCCL_E_PARA;
313 : }
314 0 : } catch (...) {
315 0 : HCCL_ERROR(
316 : "[MulQpInfo][ParseSrcPortsFromString][line: %u] port[%s] is not a valid integer.[%s]", lineCnt,
317 : token.c_str(), lineAvator.c_str());
318 0 : return HCCL_E_PARA;
319 0 : }
320 :
321 69 : CHK_PRT_RET(
322 : val == 0 || val > MultiQpSrcPortConfig::CONFIG_SRC_PORT_ID_MAX,
323 : HCCL_ERROR(
324 : "[MulQpInfo][ParseSrcPortsFromString][line: %u]src port[%s] "
325 : "should be within the range of[1, %u].[%s]",
326 : lineCnt, token.c_str(), MultiQpSrcPortConfig::CONFIG_SRC_PORT_ID_MAX, lineAvator.c_str()),
327 : HCCL_E_PARA);
328 :
329 69 : ports.emplace_back(static_cast<std::uint16_t>(val));
330 69 : if (p == std::string::npos)
331 5 : break;
332 64 : start = p + 1;
333 133 : }
334 :
335 8 : CHK_PRT_RET(
336 : ports.size() > MultiQpSrcPortConfig::CONFIG_SRC_PORT_NUM_MAX || ports.empty(),
337 : HCCL_ERROR(
338 : "[MulQpInfo][ParseSrcPortsFromString][line: %u]config ports num[%zu] more than the "
339 : "threshold[%u].[%s]",
340 : lineCnt, ports.size(), MultiQpSrcPortConfig::CONFIG_SRC_PORT_NUM_MAX, lineAvator.c_str()),
341 : HCCL_E_PARA);
342 :
343 4 : return HCCL_SUCCESS;
344 : }
345 :
346 4 : void EnvRdmaConfig::LogMultiQpSrcPortConfig() const
347 : {
348 8 : for (const auto& entry : multiQpSrcPortConfig_.ipPairToPorts) {
349 4 : std::string portsStr;
350 40 : for (size_t j = 0; j < entry.second.size(); j++) {
351 36 : if (j > 0)
352 32 : portsStr += ",";
353 36 : portsStr += std::to_string(entry.second[j]);
354 : }
355 12 : HCCL_RUN_INFO("[HCCL_ENV] MultiQpSrcPort: ipPair[%s] -> ports[%s]", entry.first.c_str(), portsStr.c_str());
356 4 : }
357 4 : }
358 :
359 43 : u32 EnvRdmaConfig::GetRdmaTrafficClass() const { return rdmaTrafficClass.Get(); }
360 :
361 43 : u32 EnvRdmaConfig::GetRdmaServerLevel() const { return rdmaServerLevel.Get(); }
362 :
363 38 : u32 EnvRdmaConfig::GetRdmaTimeOut() const { return rdmaTimeOut.Get(); }
364 :
365 38 : u32 EnvRdmaConfig::GetRdmaRetryCnt() const { return rdmaRetryCnt.Get(); }
366 :
367 39 : u32 EnvRdmaConfig::GetUboeTimeOut() const { return uboeTimeOut.Get(); }
368 :
369 276 : u32 EnvRdmaConfig::GetUbTimeOut() const { return ubTimeOut.Get(); }
370 35 : u32 EnvRdmaConfig::GetRdmaQueueNum() const { return queueNum.Get(); }
371 :
372 36 : u32 EnvRdmaConfig::GetRdmaMultiQpThreshold() const { return multiQpThreshold.Get(); }
373 :
374 83 : const MultiQpSrcPortConfig& EnvRdmaConfig::GetMultiQpSrcPortConfig() const { return multiQpSrcPortConfig_; }
375 :
376 : // EnvAlgoConfig
377 :
378 17 : void EnvAlgoConfig::Parse()
379 : {
380 : // Hcomm中不再解析HCCL_ALGO配置,因为没有实际使用
381 17 : primQueueGenName.Parse();
382 29 : HCCL_RUN_INFO(
383 : "[HCCL_ENV] PRIM_QUEUE_GEN_NAME set by %s to [%s]", primQueueGenName.GetSource(),
384 : GetPrimQueueGenName().c_str());
385 :
386 17 : bufferSize.Parse();
387 29 : HCCL_RUN_INFO("[HCCL_ENV] HCCL_BUFFSIZE set by %s to [%llu]B", bufferSize.GetSource(), GetBuffSize());
388 :
389 17 : hcclAccelerator_.Parse();
390 29 : HCCL_RUN_INFO(
391 : "[HCCL_ENV] HCCL_OP_EXPANSION_MODE set by %s to [%s]", hcclAccelerator_.GetSource(),
392 : GetHcclAccelerator().Describe().c_str());
393 17 : }
394 :
395 18 : const std::string& EnvAlgoConfig::GetPrimQueueGenName() const { return primQueueGenName.Get(); }
396 :
397 2 : const std::map<OpType, std::vector<HcclAlgoType>> EnvAlgoConfig::GetAlgoConfig() const
398 : {
399 : // hcomm不支持HCCL_ALGO解析, 返回空
400 2 : return {};
401 : }
402 :
403 27 : u64 EnvAlgoConfig::GetBuffSize() const { return bufferSize.Get(); }
404 :
405 33 : HcclAccelerator EnvAlgoConfig::GetHcclAccelerator() const { return hcclAccelerator_.Get(); }
406 :
407 : // EnvLogConfig
408 16 : void EnvLogConfig::Parse()
409 : {
410 16 : entryLogEnable.Parse();
411 28 : HCCL_RUN_INFO(
412 : "[HCCL_ENV] HCCL_ENTRY_LOG_ENABLE set by %s to [%d]", entryLogEnable.GetSource(), GetEntryLogEnable());
413 :
414 16 : cannVersion.Parse();
415 28 : HCCL_RUN_INFO("[HCCL_ENV] LD_LIBRARY_PATH set by %s to [%s]", cannVersion.GetSource(), GetCannVersion().c_str());
416 :
417 16 : dfsConfig.Parse();
418 28 : HCCL_RUN_INFO(
419 : "[HCCL_ENV] HCCL_DFS_CONFIG task_exception set by %s to [%d], cluster_heartbeat set by %s to [%d], "
420 : "rankConsistentState set by %s to [%d]",
421 : dfsConfig.GetSource(), GetDfsConfig().taskExceptionEnable, dfsConfig.GetSource(),
422 : GetDfsConfig().clusterHeartBeatEnable, dfsConfig.GetSource(), GetDfsConfig().rankConsistentState);
423 16 : }
424 :
425 156 : bool EnvLogConfig::GetEntryLogEnable() const { return entryLogEnable.Get(); }
426 :
427 17 : const std::string& EnvLogConfig::GetCannVersion() const { return cannVersion.Get(); }
428 :
429 257 : const DfsConfig& EnvLogConfig::GetDfsConfig() const { return dfsConfig.Get(); }
430 :
431 : // EnvDetourConfig
432 :
433 16 : void EnvDetourConfig::Parse()
434 : {
435 16 : detourType.Parse();
436 28 : HCCL_RUN_INFO(
437 : "[HCCL_ENV] HCCL_DETOUR set by %s to [%s]", detourType.GetSource(), GetDetourType().Describe().c_str());
438 16 : }
439 :
440 261 : HcclDetourType EnvDetourConfig::GetDetourType() const { return detourType.Get(); }
441 :
442 : } // namespace Hccl
|