Line data Source code
1 : /**
2 : * Copyright (c) 2026 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 <cstring>
11 : #include <vector>
12 :
13 : #include "hcomm_c_adpt.h"
14 : #include "hcomm_c_adpt_common.h"
15 : #include "hcomm_res.h"
16 : #include "hcomm_result_defs.h"
17 : #include "hcomm_res_defs.h"
18 : #include "log.h"
19 : #include "param_check_pub.h"
20 : #include "comm_engine_utils.h"
21 : #include "channel_process.h"
22 : #include "aicpu_ts_channel_helper.h"
23 : #ifdef ENABLE_EXPERIMENTAL
24 : #include "nic_plugin_dispatcher.h"
25 : #endif
26 :
27 : using namespace hcomm;
28 :
29 38 : HcommResult CheckUbAttr(HcommChannelDesc &channelDesc)
30 : {
31 38 : if (channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UBC_TP
32 38 : && channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UBOE
33 38 : && channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UBG
34 38 : && channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_UBC_CTP) {
35 19 : return HCCL_SUCCESS;
36 : }
37 :
38 : // check sqDepth
39 19 : if (channelDesc.ubAttr.sqDepth == 0xFFFFFFFF) { // 0xFFFFFFFF表示使用默认值
40 15 : HCCL_INFO("[%s] use default ubAttr.sqDepth.", __func__);
41 15 : return HCCL_SUCCESS;
42 : }
43 :
44 : // sqDepth的合理范围在[16, 256]
45 4 : if (channelDesc.ubAttr.sqDepth < 16 || channelDesc.ubAttr.sqDepth > 256) {
46 2 : HCCL_ERROR(
47 : "[%s] invalid ubAttr.sqDepth[%u], should be 0 or >= 16 and <= 256.", __func__, channelDesc.ubAttr.sqDepth);
48 2 : return HCCL_E_PARA;
49 : }
50 :
51 : // channelDesc.ubAttr.sqDepth调整到2的整数次幂
52 2 : auto GetNextPowerOfTwo = [](uint32_t n) -> uint32_t {
53 2 : n--;
54 2 : n |= n >> 1;
55 2 : n |= n >> 2;
56 2 : n |= n >> 4;
57 2 : n |= n >> 8;
58 2 : n |= n >> 16;
59 2 : return n + 1;
60 : };
61 :
62 2 : channelDesc.ubAttr.sqDepth = GetNextPowerOfTwo(channelDesc.ubAttr.sqDepth);
63 :
64 2 : return HCCL_SUCCESS;
65 : }
66 :
67 31 : HcommResult CheckRoceAttr(HcommChannelDesc &channelDesc)
68 : {
69 31 : if (channelDesc.remoteEndpoint.protocol != COMM_PROTOCOL_ROCE) {
70 31 : return HCCL_SUCCESS;
71 : }
72 :
73 0 : if (channelDesc.roceAttr.queueNum == INVALID_UINT) {
74 0 : channelDesc.roceAttr.queueNum = 1;
75 0 : HCCL_INFO("[%s] set roceAttr.queueNum to 1.", __func__);
76 : }
77 :
78 0 : return HCCL_SUCCESS;
79 : }
80 :
81 : namespace {
82 31 : void ApplyHcommChannelDescV1Fields(const HcommChannelDesc &channelDesc, HcommChannelDesc &channelDescFinal)
83 : {
84 31 : if (channelDesc.header.version < HCOMM_CHANNEL_VERSION_ONE) {
85 0 : return;
86 : }
87 :
88 31 : channelDescFinal.remoteEndpoint = channelDesc.remoteEndpoint;
89 31 : channelDescFinal.notifyNum = channelDesc.notifyNum;
90 31 : channelDescFinal.exchangeAllMems = channelDesc.exchangeAllMems;
91 31 : channelDescFinal.memHandles = channelDesc.memHandles;
92 31 : channelDescFinal.memHandleNum = channelDesc.memHandleNum;
93 31 : channelDescFinal.socket = channelDesc.socket;
94 31 : channelDescFinal.role = channelDesc.role;
95 31 : channelDescFinal.port = channelDesc.port;
96 : }
97 :
98 31 : HcommResult ProcessHcommChannelDescs(const HcommChannelDesc &channelDesc, HcommChannelDesc &channelDescFinal)
99 : {
100 31 : if (channelDesc.header.size < sizeof(CommAbiHeader)) {
101 0 : HCCL_ERROR("[%s] invalid channelDesc.header.size[%u].", __func__, channelDesc.header.size);
102 0 : return HCCL_E_PARA;
103 : }
104 :
105 31 : if (channelDesc.header.magicWord != channelDescFinal.header.magicWord) {
106 0 : HCCL_ERROR("[%s] channelDesc.header.magicWord[0x%08x] is invalid, expected[0x%08x].", __func__,
107 : channelDesc.header.magicWord, channelDescFinal.header.magicWord);
108 0 : return HCCL_E_PARA;
109 : }
110 :
111 31 : const uint32_t copySize = (channelDescFinal.header.size < channelDesc.header.size ? channelDescFinal.header.size
112 31 : : channelDesc.header.size)
113 0 : - sizeof(CommAbiHeader);
114 31 : CHK_SAFETY_FUNC_RET(memcpy_s(reinterpret_cast<uint8_t *>(&channelDescFinal) + sizeof(CommAbiHeader), copySize,
115 : reinterpret_cast<const uint8_t *>(&channelDesc) + sizeof(CommAbiHeader), copySize));
116 31 : ApplyHcommChannelDescV1Fields(channelDesc, channelDescFinal);
117 31 : if (channelDesc.header.version > HCOMM_CHANNEL_VERSION) {
118 0 : HCCL_RUN_WARNING("The version of provided [%u] is higher than the current version[%u], "
119 : "unsupported configuration will be ignored.",
120 : channelDesc.header.version, HCOMM_CHANNEL_VERSION);
121 31 : } else if (channelDesc.header.version < HCOMM_CHANNEL_VERSION) {
122 1 : HCCL_RUN_WARNING("The version of provided [%u] is lower than the current version[%u], "
123 : "configurations supported by later versions will be ignored.",
124 : channelDesc.header.version, HCOMM_CHANNEL_VERSION);
125 : }
126 :
127 : // qos:低版本时置默认值
128 31 : if (channelDesc.header.version <= HCOMM_CHANNEL_VERSION_ONE) {
129 1 : channelDescFinal.qos = 0xFFFFFFFFU;
130 : } else {
131 30 : channelDescFinal.qos = channelDesc.qos;
132 : }
133 :
134 : // v3:channelName,低版本时置 NULL
135 31 : if (channelDesc.header.version < HCOMM_CHANNEL_VERSION) {
136 1 : channelDescFinal.channelName = nullptr;
137 : } else {
138 30 : channelDescFinal.channelName = channelDesc.channelName;
139 30 : if (channelDescFinal.channelName != nullptr
140 1 : && reinterpret_cast<uintptr_t>(channelDescFinal.channelName) == static_cast<uintptr_t>(-1)) {
141 0 : channelDescFinal.channelName = nullptr;
142 : }
143 : }
144 :
145 31 : if (channelDescFinal.channelName != nullptr) {
146 1 : size_t nameLen = strnlen(channelDescFinal.channelName, HCOMM_CHANNEL_NAME_MAX_LEN + 1);
147 1 : if (nameLen > HCOMM_CHANNEL_NAME_MAX_LEN) {
148 0 : HCCL_ERROR("[%s] channelName too long, max len[%u].", __func__, HCOMM_CHANNEL_NAME_MAX_LEN);
149 0 : return HCCL_E_PARA;
150 : }
151 : }
152 :
153 31 : return HCOMM_SUCCESS;
154 : }
155 :
156 31 : HcommResult NormalizeHcommChannelDescs(
157 : HcommChannelDesc *channelDescs, uint32_t channelNum, std::vector<HcommChannelDesc> &channelDescFinals)
158 : {
159 31 : channelDescFinals.clear();
160 31 : channelDescFinals.reserve(channelNum);
161 62 : for (uint32_t idx = 0; idx < channelNum; ++idx) {
162 31 : HcommChannelDesc channelDescFinal{};
163 31 : HcommResult ret = HcommChannelDescInit(&channelDescFinal, 1);
164 31 : if (ret != HCOMM_SUCCESS) {
165 0 : return ret;
166 : }
167 31 : ret = ProcessHcommChannelDescs(channelDescs[idx], channelDescFinal);
168 31 : if (ret != HCOMM_SUCCESS) {
169 0 : HCCL_ERROR("[%s] failed to normalize channelDesc[%u], ret[%d].", __func__, idx, ret);
170 0 : return ret;
171 : }
172 31 : ret = CheckUbAttr(channelDescFinal);
173 31 : if (ret != HCOMM_SUCCESS) {
174 0 : HCCL_ERROR("[%s] CheckUbAttr failed, ret[%d].", __func__, ret);
175 0 : return ret;
176 : }
177 31 : ret = CheckRoceAttr(channelDescFinal);
178 31 : if (ret != HCOMM_SUCCESS) {
179 0 : HCCL_ERROR("[%s] CheckRoceAttr failed, ret[%d].", __func__, ret);
180 0 : return ret;
181 : }
182 :
183 31 : channelDescFinals.push_back(channelDescFinal);
184 : }
185 31 : return HCOMM_SUCCESS;
186 : }
187 : } // namespace
188 :
189 : // 集合通信使用,待归一到HcommChannelCreate
190 12 : HcommResult HcommCollectiveChannelCreate(EndpointHandle endpointHandle, CommEngine engine,
191 : HcommChannelDesc *channelDescs, uint32_t channelNum, ChannelHandle *channels)
192 : {
193 12 : CHK_PTR_NULL(channelDescs);
194 10 : CHK_PTR_NULL(channels);
195 10 : CHK_PRT_RET(
196 : (channelNum == 0), HCCL_ERROR("[%s]Invalid channelNum, channelNum[%u]", __func__, channelNum), HCCL_E_PARA);
197 8 : HCCL_INFO("[%s] START. endpointHandle[0x%llx], engine[%s], channelNum[%u].", __func__, endpointHandle,
198 : GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), channelNum);
199 :
200 8 : std::vector<HcommChannelDesc> channelDescFinals;
201 8 : CHK_RET(static_cast<HcclResult>(NormalizeHcommChannelDescs(channelDescs, channelNum, channelDescFinals)));
202 8 : return ChannelProcess::CreateChannelsLoop(endpointHandle, engine, channelDescFinals.data(), channelNum, channels);
203 8 : }
204 :
205 0 : HcommResult HcommChannelUpdateMemInfo(HcommMemHandle *memHandles, uint32_t memHandleNum, ChannelHandle channelHandle)
206 : {
207 0 : CHK_PTR_NULL(memHandles);
208 0 : CHK_PRT_RET((memHandleNum == 0), HCCL_ERROR("[%s]Invalid memHandleNum, memHandleNum is 0.", __func__), HCCL_E_PARA);
209 : #ifdef ENABLE_EXPERIMENTAL
210 0 : bool handled = false;
211 0 : CHK_RET(static_cast<HcclResult>(PluginChannelUpdateMemInfo(channelHandle, memHandles, memHandleNum, handled)));
212 0 : if (handled) {
213 0 : return HCCL_SUCCESS;
214 : }
215 : #endif
216 :
217 0 : return ChannelProcess::ChannelUpdateMemInfo(memHandles, memHandleNum, channelHandle);
218 : }
219 :
220 28 : HcommResult HcommChannelCreate(EndpointHandle endpointHandle, CommEngine engine, HcommChannelDesc *channelDescs,
221 : uint32_t channelNum, ChannelHandle *channels)
222 : {
223 28 : CHK_PTR_NULL(endpointHandle);
224 25 : CHK_PTR_NULL(channelDescs);
225 24 : CHK_PTR_NULL(channels);
226 24 : CHK_PRT_RET(
227 : (channelNum == 0), HCCL_ERROR("[%s]Invalid channelNum, channelNum[%u]", __func__, channelNum), HCCL_E_PARA);
228 23 : HCCL_INFO("[%s] START. endpointHandle[0x%llx], engine[%s], channelNum[%u].", __func__, endpointHandle,
229 : GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), channelNum);
230 23 : auto endpoint = GetEndpointMap().GetEndpoint(endpointHandle);
231 23 : if (endpoint != nullptr) {
232 17 : CHK_RET(RefreshEndpointContext(endpoint->GetEndpointDesc()));
233 : }
234 23 : (void)HcommResMgrInit();
235 23 : std::vector<HcommChannelDesc> channelDescFinals;
236 23 : CHK_RET(static_cast<HcclResult>(NormalizeHcommChannelDescs(channelDescs, channelNum, channelDescFinals)));
237 :
238 : #ifdef ENABLE_EXPERIMENTAL
239 23 : bool pluginHandled = false;
240 23 : CHK_RET(static_cast<HcclResult>(
241 : PluginChannelCreate(endpointHandle, engine, channelDescFinals.data(), channelNum, channels, pluginHandled)));
242 20 : if (pluginHandled) {
243 1 : return HCCL_SUCCESS;
244 : }
245 : #endif
246 :
247 19 : std::vector<ChannelHandle> hostChannelHandles(channelNum);
248 19 : ChannelHandle *targetChannels = hostChannelHandles.data();
249 :
250 19 : CHK_RET(ChannelProcess::CreateChannelsLoop(
251 : endpointHandle, engine, channelDescFinals.data(), channelNum, targetChannels));
252 19 : CHK_RET(
253 : ChannelProcess::PrepareUserChannels(targetChannels, channels, channelDescFinals.data(), channelNum, engine));
254 :
255 18 : return HCCL_SUCCESS;
256 23 : }
257 :
258 58 : HcommResult HcommChannelGet(ChannelHandle channelHandle, void **channel)
259 : {
260 58 : CHK_PTR_NULL(channel);
261 : #ifdef ENABLE_EXPERIMENTAL
262 57 : bool handled = false;
263 57 : CHK_RET(static_cast<HcclResult>(PluginChannelGet(channelHandle, channel, handled)));
264 57 : if (handled) {
265 0 : return HCCL_SUCCESS;
266 : }
267 : #endif
268 57 : return ChannelProcess::ChannelGet(channelHandle, channel);
269 : }
270 :
271 33 : HcommResult HcommChannelGetStatus(const ChannelHandle *channelList, uint32_t listNum, int32_t *statusList)
272 : {
273 33 : CHK_PTR_NULL(channelList);
274 31 : CHK_PTR_NULL(statusList);
275 29 : CHK_PRT_RET((listNum == 0), HCCL_ERROR("[%s]Invalid listNum, listNum[%u]", __func__, listNum), HCCL_E_PARA);
276 27 : (void)HcommResMgrInit();
277 : #ifdef ENABLE_EXPERIMENTAL
278 27 : bool allHandled = true;
279 58 : for (uint32_t i = 0; i < listNum; i++) {
280 31 : bool handled = false;
281 31 : CHK_RET(static_cast<HcclResult>(PluginChannelGetStatus(channelList[i], &statusList[i], handled)));
282 31 : if (!handled) {
283 31 : allHandled = false;
284 : }
285 : }
286 27 : if (allHandled) {
287 0 : return HCCL_SUCCESS;
288 : }
289 : #endif
290 :
291 27 : std::vector<CommEngine> engines;
292 27 : std::vector<HcommChannelDesc> channelDescFinals;
293 27 : std::vector<ChannelStatus> internalStatus(listNum);
294 27 : HcclResult ret = ChannelProcess::GetChannelsInfo(channelList, listNum, engines, channelDescFinals, internalStatus);
295 27 : if (ret != HCCL_SUCCESS) {
296 2 : HCCL_ERROR("[%s] GetChannelsInfo failed, ret[%d]", __func__, ret);
297 2 : return HCCL_E_INTERNAL;
298 : }
299 25 : ret = ChannelProcess::HandleStatusByEngine(
300 : channelList, listNum, engines, channelDescFinals, internalStatus, statusList);
301 25 : if (ret != HCCL_SUCCESS) {
302 0 : HCCL_ERROR("[%s] HandleStatusByEngine failed, ret[%d]", __func__, ret);
303 0 : return HCCL_E_INTERNAL;
304 : }
305 25 : return HCCL_SUCCESS;
306 27 : }
307 :
308 2 : HcommResult HcommChannelGetNotifyNum(ChannelHandle channelHandle, uint32_t *notifyNum)
309 : {
310 2 : CHK_PTR_NULL(notifyNum);
311 : #ifdef ENABLE_EXPERIMENTAL
312 1 : bool handled = false;
313 1 : CHK_RET(static_cast<HcclResult>(PluginChannelGetNotifyNum(channelHandle, notifyNum, handled)));
314 1 : if (handled) {
315 0 : return HCCL_SUCCESS;
316 : }
317 : #endif
318 1 : return ChannelProcess::ChannelGetNotifyNum(channelHandle, notifyNum);
319 : }
320 :
321 21 : HcommResult HcommChannelDestroy(const ChannelHandle *channels, uint32_t channelNum)
322 : {
323 21 : CHK_PTR_NULL(channels);
324 20 : (void)HcommResMgrInit();
325 20 : CHK_PRT_RET(
326 : (channelNum == 0), HCCL_ERROR("[%s]Invalid channelNum, channelNum[%u]", __func__, channelNum), HCCL_E_PARA);
327 19 : std::vector<ChannelHandle> builtinChannels;
328 19 : builtinChannels.reserve(channelNum);
329 39 : for (uint32_t idx = 0; idx < channelNum; ++idx) {
330 : #ifdef ENABLE_EXPERIMENTAL
331 20 : bool handled = false;
332 20 : CHK_RET(static_cast<HcclResult>(PluginChannelDestroy(channels[idx], handled)));
333 20 : if (handled) {
334 1 : continue;
335 : }
336 : #endif
337 19 : builtinChannels.push_back(channels[idx]);
338 : }
339 19 : if (builtinChannels.empty()) {
340 1 : return HCCL_SUCCESS;
341 : }
342 36 : return ChannelProcess::ChannelDestroy(
343 36 : builtinChannels.data(), builtinChannels.size(), AicpuTsChannelHelper::GetBinHandle());
344 19 : }
345 :
346 8 : HcommResult HcommChannelGetRemoteMems(
347 : ChannelHandle channelHandle, uint32_t *memNum, CommMem **remoteMem, char ***memInfos)
348 : {
349 8 : CHK_PTR_NULL(remoteMem);
350 7 : CHK_PTR_NULL(memNum);
351 6 : CHK_PTR_NULL(memInfos);
352 : #ifdef ENABLE_EXPERIMENTAL
353 6 : bool handled = false;
354 6 : CHK_RET(static_cast<HcclResult>(PluginChannelGetRemoteMems(channelHandle, memNum, remoteMem, memInfos, handled)));
355 6 : if (handled) {
356 1 : return HCCL_SUCCESS;
357 : }
358 : #endif
359 :
360 5 : return ChannelProcess::ChannelGetRemoteMems(channelHandle, memNum, remoteMem, memInfos);
361 : }
|