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 "rdma_resource_manager.h"
12 : #include "dltdt_function.h"
13 : #include "adapter_hccp.h"
14 : #include "adapter_tdt.h"
15 : #include "externalinput_pub.h"
16 : #include "adapter_hccp_common.h"
17 : #include "adapter_rts_common.h"
18 : #include "network_manager_pub.h"
19 :
20 : namespace hccl {
21 : // 预留后续扩展多个池子信息,使用逗号,间隔resv_mem_$dev_id=$type_$pool_id_$total_mem_size_$page_size
22 : #define HCCN_RESV_MEM_TYPE_OFFSET (0)
23 : #define HCCN_RESV_MEM_POOLID_OFFSET (1)
24 : #define HCCN_RESV_MEM_PAGESIZE_OFFSET (3)
25 : #define HCCN_RSCV_MEM_COUNT (4)
26 : #define HCCN_RESV_MEM_PAGESIZE_64K (64)
27 : constexpr u32 RETRY_CQE_ARRAY_SIZE = 128; // 重执行时获取的CQE数组的最大数量,最大128
28 66 : RdmaResourceManager::RdmaResourceManager() : nicDeploy_(NICDeployment::NIC_DEPLOYMENT_DEVICE) {}
29 :
30 66 : RdmaResourceManager::~RdmaResourceManager() { DeInit(); }
31 :
32 541 : RdmaResourceManager& RdmaResourceManager::GetInstance()
33 : {
34 607 : static RdmaResourceManager rdmaInstance[MAX_MODULE_DEVICE_NUM + 1];
35 541 : s32 deviceLogicId = INVALID_INT;
36 541 : HcclResult ret = hrtGetDevice(&deviceLogicId);
37 541 : if (ret == HCCL_SUCCESS && (static_cast<u32>(deviceLogicId) < MAX_MODULE_DEVICE_NUM)) {
38 541 : HCCL_INFO("[RdmaResourceManager::GetInstance]deviceLogicID[%d]", deviceLogicId);
39 541 : return rdmaInstance[deviceLogicId];
40 : }
41 0 : HCCL_WARNING("[RdmaResourceManager::GetInstance]deviceLogicID[%d] is invalid, ret[%d]", deviceLogicId, ret);
42 0 : return rdmaInstance[MAX_MODULE_DEVICE_NUM];
43 : }
44 :
45 32 : HcclResult RdmaResourceManager::Init()
46 : {
47 32 : HcclResult ret = InitExternalInput();
48 32 : CHK_PRT_RET(
49 : ret != HCCL_SUCCESS,
50 : HCCL_ERROR("[RdmaResourceManager][Init]errNo[0x%016llx] init external input error.", HCCL_ERROR_CODE(ret)),
51 : HCCL_E_PARA);
52 32 : HCCL_INFO("[RdmaResourceManager][Init] Init ExternalInput success!");
53 :
54 32 : CHK_RET(hrtGetDevice(&deviceLogicId_));
55 32 : CHK_RET(hrtGetDevicePhyIdByIndex(static_cast<u32>(deviceLogicId_), devicePhyId_, true));
56 32 : CHK_RET(NetworkManager::GetInstance(deviceLogicId_).Init(nicDeploy_, false, devicePhyId_, true));
57 32 : HCCL_DEBUG(
58 : "[RdmaResourceManager][Init] NetworkManager Init, deviceLogicId[%d], devicePhyId[%u], nicDeployment_[%d]",
59 : deviceLogicId_, devicePhyId_, nicDeploy_);
60 :
61 32 : std::vector<HcclIpAddress> deviceIPs;
62 32 : CHK_RET(hrtRaGetDeviceIP(devicePhyId_, deviceIPs));
63 32 : CHK_PRT_RET(
64 : deviceIPs.size() < 1,
65 : HCCL_ERROR(
66 : "[RdmaResourceManager][Init] Get ip address failed, deviceLogicId[%d], devicePhyId[%u]", deviceLogicId_,
67 : devicePhyId_),
68 : HCCL_E_INTERNAL);
69 :
70 32 : for (u32 ipIdex = 0; ipIdex < deviceIPs.size(); ipIdex++) {
71 32 : if (deviceIPs[ipIdex].IsInvalid()) {
72 0 : continue;
73 : }
74 : // port传入的值为无效值0xFFFFFFFF, 不启动监听
75 32 : ret = NetworkManager::GetInstance(deviceLogicId_).StartNic(deviceIPs[ipIdex], port_, true);
76 32 : CHK_PRT_RET(
77 : ret != HCCL_SUCCESS,
78 : HCCL_ERROR(
79 : "[RdmaResourceManager][Init] Start nic ipaddr[%s] failed", deviceIPs[ipIdex].GetReadableAddress()),
80 : ret);
81 32 : ipAddr_ = deviceIPs[ipIdex];
82 32 : break;
83 : }
84 32 : if (ipAddr_.IsInvalid()) {
85 0 : HCCL_ERROR("[RdmaResourceManager][Init] No valid ipAddr, devicePhyId is [%u].", devicePhyId_);
86 0 : return HCCL_E_NOT_FOUND;
87 : }
88 32 : CHK_RET(NetworkManager::GetInstance(deviceLogicId_).GetRdmaHandleByIpAddr(ipAddr_, rdmaHandle_));
89 32 : CHK_PTR_NULL(rdmaHandle_);
90 32 : HCCL_INFO(
91 : "[RdmaResourceManager][Init] Start nic, devicePhyId is [%u], ip address[%s], port[%u].", devicePhyId_,
92 : this->ipAddr_.GetReadableAddress(), this->port_);
93 :
94 32 : CHK_RET(HrtRaGetNotifyBaseAddr(rdmaHandle_, ¬ifyBaseVa_, ¬ifyTotalSize_));
95 32 : HCCL_INFO("[RdmaResourceManager][Init] NotifyBaseAddr addr[%llu] size[%llu].", notifyBaseVa_, notifyTotalSize_);
96 :
97 32 : notifyMrInfo_.addr = reinterpret_cast<void*>(notifyBaseVa_);
98 32 : notifyMrInfo_.size = notifyTotalSize_;
99 32 : notifyMrInfo_.access = RA_ACCESS_REMOTE_WRITE | RA_ACCESS_LOCAL_WRITE | RA_ACCESS_REMOTE_READ;
100 32 : CHK_RET(hrtRaRegGlobalMr(rdmaHandle_, notifyMrInfo_, mrHandle_));
101 32 : HCCL_RUN_INFO(
102 : "[RdmaResourceManager][Init] Register NotifyBaseAddr addr[%p] size[%llu] key[%u]", notifyMrInfo_.addr,
103 : notifyMrInfo_.size, notifyMrInfo_.lkey);
104 32 : CHK_RET(InitResvMemInfo());
105 32 : return HCCL_SUCCESS;
106 32 : }
107 :
108 2 : void RdmaResourceManager::SetDisableLiteThread(bool disable)
109 : {
110 2 : s32 deviceLogicId = INVALID_INT;
111 2 : hrtGetDevice(&deviceLogicId);
112 2 : NetworkManager::GetInstance(deviceLogicId).SetDisableLiteThread(disable);
113 2 : }
114 :
115 358 : HcclResult RdmaResourceManager::GetRdmaHandle(RdmaHandle& rdmaHandle)
116 : {
117 358 : CHK_PTR_NULL(rdmaHandle_);
118 358 : rdmaHandle = rdmaHandle_;
119 358 : return HCCL_SUCCESS;
120 : }
121 :
122 98 : HcclResult RdmaResourceManager::DeInit()
123 : {
124 98 : if (rdmaHandle_ == nullptr) {
125 66 : HCCL_INFO("[RdmaResourceManager][DeInit] RDMA resource has been already deinited!");
126 66 : return HCCL_SUCCESS;
127 : }
128 32 : CHK_PTR_NULL(mrHandle_);
129 32 : CHK_RET(hrtRaDeRegGlobalMr(rdmaHandle_, mrHandle_));
130 32 : CHK_RET(NetworkManager::GetInstance(deviceLogicId_).StopNic(ipAddr_, port_));
131 32 : rdmaHandle_ = nullptr;
132 32 : HCCL_INFO(
133 : "[RdmaResourceManager][DeInit] Stop nic, devicePhyId is [%u], ip address[%s], port[%u].", devicePhyId_,
134 : ipAddr_.GetReadableAddress(), port_);
135 32 : CHK_RET(NetworkManager::GetInstance(deviceLogicId_).DeInit(nicDeploy_));
136 32 : return HCCL_SUCCESS;
137 : }
138 :
139 0 : HcclResult RdmaResourceManager::GetCqeErrInfo(struct CqeErrInfo* infoList, u32* num)
140 : {
141 0 : CHK_PTR_NULL(rdmaHandle_);
142 0 : return hrtRaGetCqeErrInfoList(rdmaHandle_, infoList, num);
143 : }
144 :
145 0 : HcclResult RdmaResourceManager::GetCqeErrInfoByQpn(u32 qpn, struct HcclErrCqeInfo* errCqeList, u32* num)
146 : {
147 0 : CHK_PTR_NULL(rdmaHandle_);
148 0 : u32 qpnNum = RETRY_CQE_ARRAY_SIZE;
149 0 : u32 listLen = *num;
150 0 : std::unique_lock<std::mutex> lock(cqeErrMapMutex_);
151 0 : struct CqeErrInfo cqeErrInfolist[qpnNum] = {};
152 0 : CHK_RET(hrtRaGetCqeErrInfoList(rdmaHandle_, cqeErrInfolist, &qpnNum));
153 0 : for (u32 i = 0; i < qpnNum; i++) {
154 0 : u32 errQpn = cqeErrInfolist[i].qpn;
155 0 : cqeErrPerQP_[errQpn].push(cqeErrInfolist[i]);
156 : }
157 0 : if (cqeErrPerQP_.empty() || cqeErrPerQP_.find(qpn) == cqeErrPerQP_.end()) {
158 0 : *num = 0;
159 : } else {
160 0 : *num = cqeErrPerQP_[qpn].size();
161 0 : if (*num > listLen) {
162 0 : *num = listLen;
163 0 : HCCL_WARNING("[GetCqeErrInfoByQpn] GetCqeErrInfo num is larger than infoList user given.");
164 : }
165 0 : u32 i = 0;
166 0 : while (!cqeErrPerQP_[qpn].empty() && i < listLen) {
167 0 : errCqeList[i].qpn = cqeErrPerQP_[qpn].front().qpn;
168 0 : errCqeList[i].status = cqeErrPerQP_[qpn].front().status;
169 0 : errCqeList[i].time = cqeErrPerQP_[qpn].front().time;
170 0 : time_t tmpt = static_cast<time_t>(errCqeList[i].time.tv_sec);
171 : struct tm errTime;
172 0 : localtime_r(&tmpt, &errTime);
173 0 : HCCL_INFO(
174 : "[GetCqeErrInfoByQpn] Err Cqe status[%d], qpn[%d], time[%04u-%02d-%02d %02d:%0d:%02d.%06u]",
175 : errCqeList[i].status, errCqeList[i].qpn, errTime.tm_year + TIME_FROM_1900, errTime.tm_mon + 1,
176 : errTime.tm_mday, errTime.tm_hour, errTime.tm_min, errTime.tm_sec,
177 : static_cast<u32>(errCqeList[i].time.tv_usec));
178 0 : cqeErrPerQP_[qpn].pop();
179 0 : i++;
180 : }
181 : }
182 0 : return HCCL_SUCCESS;
183 0 : }
184 :
185 90 : HcclResult RdmaResourceManager::GetNotifyMrInfo(struct MrInfoT& mrInfo)
186 : {
187 90 : CHK_PTR_NULL(rdmaHandle_);
188 90 : mrInfo.lkey = notifyMrInfo_.lkey;
189 90 : HCCL_RUN_INFO("[RdmaResourceManager][GetNotifyMrInfo] SyncMem key[%u].", mrInfo.lkey);
190 90 : return HCCL_SUCCESS;
191 : }
192 :
193 32 : HcclResult RdmaResourceManager::InitResvMemInfo()
194 : {
195 32 : std::string flagValue;
196 32 : std::vector<std::string> parts;
197 32 : std::vector<std::string> tokens;
198 32 : std::string token;
199 64 : HcclResult vRet = HrtRaGetHccnCfg(
200 32 : static_cast<std::uint32_t>(nicDeploy_), devicePhyId_, HccnCfgKeyT::HCCN_RESV_MEM_INFO, flagValue);
201 32 : if ((vRet != HCCL_SUCCESS) || (flagValue.empty())) {
202 31 : return vRet;
203 : }
204 1 : HCCL_DEBUG("[InitResvMemInfo] resvMemInfo[%s].", flagValue.c_str());
205 1 : std::istringstream partStream(flagValue);
206 2 : while (std::getline(partStream, token, ',')) {
207 1 : parts.push_back(token);
208 : }
209 2 : for (auto s : parts) {
210 1 : std::istringstream tokenStream(s);
211 5 : while (std::getline(tokenStream, token, '_')) {
212 4 : tokens.push_back(token);
213 : }
214 1 : if (tokens.size() != HCCN_RSCV_MEM_COUNT) {
215 0 : HCCL_ERROR(
216 : "[InitResvMemInfo] resvMemInfo count[%u] is not equal [%u].", tokens.size(), HCCN_RSCV_MEM_COUNT);
217 0 : return HCCL_E_PARA;
218 : }
219 5 : for (u32 i = 0; i < tokens.size(); i++) {
220 10 : for (char c : tokens[i]) {
221 6 : if (!std::isdigit(c)) {
222 0 : HCCL_ERROR("[InitResvMemInfo] resvMemInfo[%s] is invalid.", tokens[i].c_str());
223 0 : return HCCL_E_PARA;
224 : }
225 : }
226 : }
227 :
228 1 : u32 type = std::stoi(tokens[HCCN_RESV_MEM_TYPE_OFFSET]);
229 1 : u32 pageSize = std::stoi(tokens[HCCN_RESV_MEM_PAGESIZE_OFFSET]);
230 1 : u32 poolId = std::stoi(tokens[HCCN_RESV_MEM_POOLID_OFFSET]);
231 : int supportLite;
232 1 : if (HCCL_SUCCESS == HrtGetRdmaLiteStatus(rdmaHandle_, &supportLite)) {
233 1 : if (((2 == supportLite) && (HCCN_RESV_MEM_PAGESIZE_64K == pageSize)) || (1 == supportLite)) {
234 0 : resvMemInfo_.insert({type, poolId});
235 : }
236 : }
237 1 : tokens.clear();
238 1 : }
239 :
240 1 : return HCCL_SUCCESS;
241 32 : }
242 :
243 10 : HcclResult RdmaResourceManager::GetResvMemPoolIdByType(u32 type, u32& poolId)
244 : {
245 10 : auto it = resvMemInfo_.find(type);
246 10 : if (it == resvMemInfo_.end()) {
247 10 : HCCL_WARNING("[RdmaResourceManager][GetResvMemPoolIdByType] can not find [%u].", type);
248 10 : return HCCL_E_NOT_FOUND;
249 : }
250 :
251 0 : poolId = resvMemInfo_[type];
252 0 : HCCL_RUN_INFO("[RdmaResourceManager][GetResvMemPoolIdByType] type[%u], resvMemPoolId [%u].", type, poolId);
253 0 : return HCCL_SUCCESS;
254 : }
255 :
256 : } // namespace hccl
|