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 "endpoint.h"
12 : #include <functional>
13 : #include "aicpu_ts_roce_endpoint.h"
14 : #include "cpu_roce_endpoint.h"
15 : #include "urma_endpoint.h"
16 : #include "ub_mem_endpoint.h"
17 : #include "uboe_endpoint.h"
18 : #include "ub_rtp_endpoint.h"
19 : #include "cpu_urma_endpoint.h"
20 : #include "aicputs_hccs_endpoint.h"
21 : #include "hccp_nda.h"
22 : #include "adapter_rts_common.h"
23 : #include "rdma_handle_manager.h"
24 : #include "proc_reged_mem_mgr_cache.h"
25 : #include "dfx/endpoint_monitor.h"
26 : #include "log.h"
27 :
28 : namespace hcomm {
29 89 : static bool IsSupported(const EndpointDesc& endpointDesc)
30 : {
31 89 : bool protocolSupported = false;
32 89 : bool locTypeSupported = false;
33 89 : switch (endpointDesc.protocol) {
34 89 : case COMM_PROTOCOL_ROCE:
35 : case COMM_PROTOCOL_UBC_TP:
36 : case COMM_PROTOCOL_UB_CTP:
37 : case COMM_PROTOCOL_UB_MEM:
38 : case COMM_PROTOCOL_PCIE:
39 : case COMM_PROTOCOL_UBOE:
40 : case COMM_PROTOCOL_UB_RTP:
41 : case COMM_PROTOCOL_HCCS:
42 89 : protocolSupported = true;
43 89 : break;
44 0 : default:
45 0 : return false;
46 : }
47 89 : switch (endpointDesc.loc.locType) {
48 89 : case ENDPOINT_LOC_TYPE_DEVICE:
49 : case ENDPOINT_LOC_TYPE_HOST:
50 89 : locTypeSupported = true;
51 89 : break;
52 0 : default:
53 0 : return false;
54 : }
55 :
56 89 : return protocolSupported && locTypeSupported;
57 : }
58 :
59 332 : Endpoint::Endpoint(const EndpointDesc& endpointDesc) { endpointDesc_ = endpointDesc; }
60 :
61 332 : Endpoint::~Endpoint()
62 : {
63 332 : ReleaseEndpointMonitor(reinterpret_cast<EndpointHandle>(this));
64 332 : ReleaseCache();
65 : // JettyContext 由 unique_ptr 自动析构:refCount 归 0 销毁 jetty,refCount > 0 告警避免 use-after-free。
66 : // 控制面资源(设备上下文/注册内存)由各子类析构处理,与数据面 jetty 资源解耦。
67 : // SharedJettyMgr 反查记录由 HcommEndpointDestroy 在 RemoveEndpoint 前摘除(运行期单例确定存活),
68 : // 不在 ~Endpoint 调用,规避 g_EndpointMap 静态析构与 SharedJettyMgr 单例析构顺序不确定的风险。
69 332 : }
70 :
71 : HcclResult
72 6 : Endpoint::AcquireSharedJetty(const std::function<HcclResult(SharedJettyCtx&)>& provideCtx, SharedJettyCtx& outCtx)
73 : {
74 6 : JettyContext* ctx = GetJettyContext();
75 6 : CHK_PTR_NULL(ctx);
76 6 : return ctx->Acquire(provideCtx, outCtx);
77 : }
78 :
79 0 : HcclResult Endpoint::AcquireSharedRemoteJetty(
80 : const uint8_t* remoteQpKey, uint32_t keySize, bool& needImport, uint64_t& handle, void*& handlePtr, uint32_t& tpn)
81 : {
82 0 : JettyContext* ctx = GetJettyContext();
83 0 : CHK_PTR_NULL(ctx);
84 0 : return ctx->AcquireSharedRemoteJetty(remoteQpKey, keySize, needImport, handle, handlePtr, tpn);
85 : }
86 :
87 0 : HcclResult Endpoint::PublishSharedRemoteJetty(
88 : const uint8_t* remoteQpKey, uint32_t keySize, uint64_t handle, void* handlePtr, uint32_t tpn)
89 : {
90 0 : JettyContext* ctx = GetJettyContext();
91 0 : CHK_PTR_NULL(ctx);
92 0 : return ctx->PublishSharedRemoteJetty(remoteQpKey, keySize, handle, handlePtr, tpn);
93 : }
94 :
95 7 : HcclResult Endpoint::ReleaseSharedJetty()
96 : {
97 7 : JettyContext* ctx = GetJettyContext();
98 7 : CHK_PTR_NULL(ctx);
99 7 : return ctx->Release();
100 : }
101 :
102 13 : JettyContext* Endpoint::GetJettyContext()
103 : {
104 13 : std::call_once(jettyContextOnce_, [this] {
105 4 : jettyContext_ = std::make_unique<JettyContext>();
106 4 : });
107 13 : return jettyContext_.get();
108 : }
109 :
110 89 : HcclResult Endpoint::CreateEndpoint(const EndpointDesc& endpointDesc, std::unique_ptr<Endpoint>& endpointPtr)
111 : {
112 89 : if (!IsSupported(endpointDesc)) {
113 0 : HCCL_ERROR(
114 : "[%s]endpointDesc is not supported. endpointDesc.protocol [%d] endpointDesc.loc.locType [%d].", __func__,
115 : endpointDesc.protocol, endpointDesc.loc.locType);
116 0 : return HCCL_E_PARA;
117 : }
118 :
119 89 : HCCL_INFO(
120 : "[%s]endpointDesc.protocol [%d] endpointDesc.loc.locType [%d].", __func__, endpointDesc.protocol,
121 : endpointDesc.loc.locType);
122 :
123 89 : return CreateEndpointBase(endpointDesc, endpointPtr);
124 : }
125 :
126 89 : HcclResult Endpoint::CreateEndpointBase(const EndpointDesc& endpointDesc, std::unique_ptr<Endpoint>& endpointPtr)
127 : {
128 : using EndpointCreator = std::function<std::unique_ptr<Endpoint>(const EndpointDesc&)>;
129 : struct Entry {
130 : CommProtocol protocol;
131 : EndpointLocType locType;
132 : EndpointCreator creator;
133 : };
134 : static const Entry table[] = {
135 : {COMM_PROTOCOL_ROCE, ENDPOINT_LOC_TYPE_HOST,
136 22 : [](const EndpointDesc& d) {
137 18 : return std::make_unique<CpuRoceEndpoint>(d);
138 : }},
139 : {COMM_PROTOCOL_UBC_TP, ENDPOINT_LOC_TYPE_HOST,
140 4 : [](const EndpointDesc& d) {
141 0 : return std::make_unique<CpuUrmaEndpoint>(d);
142 : }},
143 : {COMM_PROTOCOL_UB_CTP, ENDPOINT_LOC_TYPE_HOST,
144 4 : [](const EndpointDesc& d) {
145 0 : return std::make_unique<CpuUrmaEndpoint>(d);
146 : }},
147 : {COMM_PROTOCOL_UBC_TP, ENDPOINT_LOC_TYPE_DEVICE,
148 4 : [](const EndpointDesc& d) {
149 0 : return std::make_unique<UrmaEndpoint>(d);
150 : }},
151 : {COMM_PROTOCOL_UB_CTP, ENDPOINT_LOC_TYPE_DEVICE,
152 24 : [](const EndpointDesc& d) {
153 20 : return std::make_unique<UrmaEndpoint>(d);
154 : }},
155 : {COMM_PROTOCOL_UB_MEM, ENDPOINT_LOC_TYPE_DEVICE,
156 21 : [](const EndpointDesc& d) {
157 17 : return std::make_unique<UbMemEndpoint>(d);
158 : }},
159 : {COMM_PROTOCOL_PCIE, ENDPOINT_LOC_TYPE_DEVICE,
160 4 : [](const EndpointDesc& d) {
161 0 : return std::make_unique<UbMemEndpoint>(d);
162 : }},
163 : {COMM_PROTOCOL_UBOE, ENDPOINT_LOC_TYPE_DEVICE,
164 17 : [](const EndpointDesc& d) {
165 13 : return std::make_unique<UboeEndpoint>(d);
166 : }},
167 : {COMM_PROTOCOL_UB_RTP, ENDPOINT_LOC_TYPE_DEVICE,
168 6 : [](const EndpointDesc& d) {
169 2 : return std::make_unique<UbRtpEndpoint>(d);
170 : }},
171 : {COMM_PROTOCOL_ROCE, ENDPOINT_LOC_TYPE_DEVICE,
172 5 : [](const EndpointDesc& d) {
173 1 : return std::make_unique<AicpuTsRoceEndpoint>(d);
174 : }},
175 : {COMM_PROTOCOL_HCCS, ENDPOINT_LOC_TYPE_DEVICE,
176 4 : [](const EndpointDesc& d) {
177 16 : return std::make_unique<AicpuTsHccsEndpoint>(d);
178 : }},
179 89 : };
180 :
181 552 : for (const auto& entry : table) {
182 550 : if (entry.protocol == endpointDesc.protocol && entry.locType == endpointDesc.loc.locType) {
183 87 : EXCEPTION_CATCH(endpointPtr = entry.creator(endpointDesc), return HCCL_E_PTR);
184 87 : return HCCL_SUCCESS;
185 : }
186 : }
187 :
188 2 : HCCL_ERROR(
189 : "[%s] failed, endpointDesc.protocol [%d] and endpointDesc.loc.locType [%d] do not match.", __func__,
190 : endpointDesc.protocol, endpointDesc.loc.locType);
191 2 : return HCCL_E_PARA;
192 : }
193 :
194 1 : HcclResult Endpoint::CheckFeature(const EndpointDesc& endpointDesc, HcommEndpointFeatureType featureType, bool& value)
195 : {
196 1 : if (featureType == HCOMM_ENDPOINT_FEATURE_NDA) {
197 1 : if (endpointDesc.protocol != COMM_PROTOCOL_ROCE || endpointDesc.loc.locType != ENDPOINT_LOC_TYPE_HOST) {
198 0 : HCCL_WARNING(
199 : "[%s] not support NDA, protocol[%d], locType[%d]", __func__, endpointDesc.protocol,
200 : endpointDesc.loc.locType);
201 0 : value = false;
202 0 : return HCCL_SUCCESS;
203 : }
204 :
205 1 : Hccl::IpAddress ipAddr{};
206 1 : CHK_RET(CommAddrToIpAddress(endpointDesc.commAddr, ipAddr));
207 1 : s32 devId = 0;
208 1 : CHK_RET(hrtGetDevice(&devId));
209 1 : u32 devPhyId = 0;
210 1 : CHK_RET(hrtGetDevicePhyIdByIndex(devId, devPhyId));
211 :
212 1 : auto& rdmaHandleMgr = Hccl::RdmaHandleManager::GetInstance();
213 : void* rdmaHandle = static_cast<void*>(
214 1 : rdmaHandleMgr.GetByAddr(devPhyId, Hccl::LinkProtoType::RDMA, ipAddr, Hccl::PortDeploymentType::HOST_NET));
215 1 : CHK_PTR_NULL(rdmaHandle);
216 :
217 1 : s32 directFlag = 0;
218 1 : s32 ret = RaNdaGetDirectFlag(rdmaHandle, &directFlag);
219 1 : CHK_PRT_RET(
220 : ret != HCCL_SUCCESS, HCCL_ERROR("[%s] failed to get directFlag, ret[%d]", __func__, ret), HCCL_E_INTERNAL);
221 1 : value = (directFlag != DIRECT_FLAG_NOTSUPP);
222 1 : HCCL_INFO(
223 : "[%s] %s NDA, rdmaHandle[%p], directFlag[%d]", __func__, value ? "support" : "not support", rdmaHandle,
224 : directFlag);
225 : } else {
226 0 : HCCL_WARNING("[%s] unsupported featureType[%d]", __func__, featureType);
227 0 : value = false;
228 : }
229 :
230 1 : return HCCL_SUCCESS;
231 : }
232 :
233 200 : HcclResult Endpoint::AttachCache(const MemMgrCacheKey& key, std::function<std::shared_ptr<RegedMemMgr>()> creator)
234 : {
235 200 : cacheKey_ = key;
236 200 : cacheKeepAlive_ = ProcRegedMemMgrCache::GetHolder();
237 200 : regedMemMgr_ = cacheKeepAlive_->GetOrCreate(cacheKey_, std::move(creator));
238 200 : if (regedMemMgr_ == nullptr) {
239 0 : ReleaseCache();
240 0 : return HCCL_E_INTERNAL;
241 : }
242 200 : return HCCL_SUCCESS;
243 : }
244 :
245 334 : void Endpoint::ReleaseCache()
246 : {
247 334 : if (cacheKeepAlive_ == nullptr) {
248 131 : return;
249 : }
250 203 : cacheKeepAlive_->Release(cacheKey_);
251 203 : cacheKeepAlive_.reset();
252 : }
253 :
254 23 : void Endpoint::AttachMonitor(s32 logicId) { monitorKeepAlive_ = EndpointMonitor::GetHolder(logicId); }
255 :
256 20 : HcclResult Endpoint::RegisterToEndpointMonitor(s32 logicId, EndpointHandle handle)
257 : {
258 20 : CHK_PRT_RET(
259 : monitorKeepAlive_ == nullptr, HCCL_ERROR("[Endpoint][%s] monitor not attached", __func__), HCCL_E_INTERNAL);
260 19 : return monitorKeepAlive_->RegisterToEndpointMonitor(logicId, handle);
261 : }
262 :
263 389 : void Endpoint::ReleaseEndpointMonitor(EndpointHandle handle)
264 : {
265 389 : if (monitorKeepAlive_ == nullptr) {
266 366 : return;
267 : }
268 23 : monitorKeepAlive_->RemoveEpHandleFromEndpointMonitor(handle);
269 23 : monitorKeepAlive_.reset();
270 : }
271 : } // namespace hcomm
|