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 "host_rdma_connection.h"
11 : #include "dtype_common.h"
12 : #include "exchange_rdma_conn_dto.h"
13 : #include "hccp.h"
14 :
15 : namespace hcomm {
16 : constexpr u32 WAIT_US_COUNT = 1000;
17 : constexpr uint32_t TC_TEMP = 132;
18 : constexpr uint32_t SL_TEMP = 4;
19 : constexpr uint32_t RETRY_CNT_TEMP = 7;
20 : constexpr uint32_t RETRY_TIME_TEMP = 20;
21 :
22 23 : HostRdmaConnection::HostRdmaConnection(Hccl::Socket *socket, RdmaHandle rdmaHandle):
23 23 : socket_(socket), rdmaHandle_(rdmaHandle) {}
24 :
25 14 : HcclResult HostRdmaConnection::Init()
26 : {
27 14 : if (rdmaConnStatus_ != RdmaConnStatus::CLOSED) {
28 1 : HCCL_INFO("[HostRdmaConnection][%s] status[%s] is not need init.",
29 : __func__, rdmaConnStatus_.Describe().c_str());
30 1 : return HCCL_SUCCESS;
31 : }
32 :
33 13 : int qpMode = 0;
34 : DevType devType;
35 13 : CHK_RET(hrtGetDeviceType(devType));
36 13 : if (devType == DevType::DEV_TYPE_950 || devType == DevType::DEV_TYPE_960) {
37 8 : qpMode = Hccl::OPBASE_QP_MODE;
38 5 : } else if (devType == DevType::DEV_TYPE_910B) {
39 0 : qpMode = Hccl::QP_FLAG_RC;
40 : } else {
41 5 : HCCL_ERROR("Cannot support this device type!"
42 : "errNo[0x%016llx], device type[%d]",
43 : HCCL_ERROR_CODE(HcclResult::HCCL_E_NOT_SUPPORT), devType);
44 5 : return HCCL_E_NOT_SUPPORT;
45 : }
46 8 : qpInfo_.qpMode = qpMode;
47 8 : qpInfo_.rdmaHandle = rdmaHandle_;
48 8 : rdmaConnStatus_ = RdmaConnStatus::INIT;
49 8 : return HCCL_SUCCESS;
50 : }
51 :
52 :
53 27 : HostRdmaConnection::~HostRdmaConnection()
54 : {
55 23 : if (rdmaConnStatus_ == RdmaConnStatus::CLOSED || rdmaConnStatus_ == RdmaConnStatus::INIT) {
56 19 : return;
57 : }
58 4 : HcclResult ret = DestroyQp();
59 4 : if (ret != HCCL_SUCCESS) {
60 1 : HCCL_ERROR("[%s]call DestroyQp failed: hcclRet -> %d", __func__, ret);
61 : }
62 23 : }
63 :
64 0 : std::string HostRdmaConnection::Describe() const
65 : {
66 0 : return Hccl::StringFormat("HostRdmaConnection[status=%s]", rdmaConnStatus_.Describe().c_str());
67 : }
68 :
69 7 : HcclResult HostRdmaConnection::CreateQp()
70 : {
71 7 : if (socket_->GetStatus() != Hccl::SocketStatus::OK) {
72 1 : HCCL_WARNING("[HostRdmaConnection::CreateQp] socket status is not ok, please");
73 1 : return HCCL_E_AGAIN;
74 : }
75 :
76 : // 创建receive & send channel,用于poll cq,避免软件一直轮询cq
77 6 : HCCL_INFO("HostRdmaConnection CreateCompChannel");
78 6 : s32 ret = RaCreateCompChannel(qpInfo_.rdmaHandle, &sendCompChannel_);
79 6 : CHK_PRT_RET(ret != 0,
80 : HCCL_ERROR("[HostRdmaConnection::CreateQp][CreateSendCompChannel]errNo[0x%016llx] RaCreateCompChannel fail. "
81 : "return[%d], params: rdmaHandle[%p], sendCompChannel[%p]",
82 : HCCL_ERROR_CODE(HCCL_E_NETWORK), ret, qpInfo_.rdmaHandle, &sendCompChannel_),
83 : HCCL_E_NETWORK);
84 6 : ret = RaCreateCompChannel(qpInfo_.rdmaHandle, &recvCompChannel_);
85 6 : CHK_PRT_RET(ret != 0,
86 : HCCL_ERROR("[HostRdmaConnection::CreateQp][CreateReceiveCompChannel]errNo[0x%016llx] RaCreateCompChannel fail. "
87 : "return[%d], params: rdmaHandle[%p], rcvCompChannel[%p]",
88 : HCCL_ERROR_CODE(HCCL_E_NETWORK), ret, qpInfo_.rdmaHandle, &recvCompChannel_),
89 : HCCL_E_NETWORK);
90 :
91 : // 创建CQ和QP
92 : // qp创建时不指定srq/srq cq/srq context,由qp创建时创建独立的sq和rq,并创建对应的cq
93 : // cq for sq句柄保存在qpInfo_.sendCq中; cq for rq句柄保存在qpInfo_.receiveCq变量中
94 6 : HCCL_INFO("HostRdmaConnection CreateCqAndQp");
95 6 : CHK_RET(Hccl::HrtRaCreateQpWithCq(qpInfo_.rdmaHandle, -1, -1, sendCompChannel_,
96 : recvCompChannel_, qpInfo_, isHdcMode_));
97 :
98 5 : struct QosAttr qosAttr = {0};
99 5 : qosAttr.tc = qpInfo_.trafficClass;
100 5 : qosAttr.sl = qpInfo_.serviceLevel;
101 5 : HCCL_INFO("[%s]Set qp qos success by config, TC[%u] SL[%u]", __func__, qosAttr.tc, qosAttr.sl);
102 5 : roceAttr_.tc = qpInfo_.trafficClass;
103 5 : roceAttr_.sl = qpInfo_.serviceLevel;
104 5 : roceAttr_.retryCnt = qpInfo_.retryCnt;
105 5 : roceAttr_.retryInterval = qpInfo_.retryInterval;
106 :
107 5 : ret = RaSetQpAttrQos(qpInfo_.qpHandle, &qosAttr);
108 5 : CHK_PRT_RET(ret != 0,
109 : HCCL_ERROR("[HostRdmaConnection::CreateQp][SetQpAttrQos]errNo[0x%016llx] RaSetQpAttrQos fail. "
110 : "return[%d], params: qpHandle[%p], trafficClass[%u], serviceLevel[%u]",
111 : HCCL_ERROR_CODE(HCCL_E_NETWORK), ret, qpInfo_.qpHandle, qosAttr.tc, qosAttr.sl),
112 : HCCL_E_NETWORK);
113 4 : ret = RaSetQpAttrTimeout(qpInfo_.qpHandle, &(qpInfo_.retryInterval));
114 4 : CHK_PRT_RET(ret != 0,
115 : HCCL_ERROR("[HostRdmaConnection::CreateQp][SetQpAttrTimeout]errNo[0x%016llx] RaSetQpAttrTimeout fail. "
116 : "return[%d], params: qpHandle[%p], retryInterval[%u]",
117 : HCCL_ERROR_CODE(HCCL_E_NETWORK), ret, qpInfo_.qpHandle, qpInfo_.retryInterval),
118 : HCCL_E_NETWORK);
119 3 : ret = RaSetQpAttrRetryCnt(qpInfo_.qpHandle, &(qpInfo_.retryCnt));
120 3 : CHK_PRT_RET(ret != 0,
121 : HCCL_ERROR("[HostRdmaConnection::CreateQp][SetQpAttrRetryCnt]errNo[0x%016llx] RaSetQpAttrRetryCnt fail. "
122 : "return[%d], params: qpHandle[%p], retryCnt[%u]",
123 : HCCL_ERROR_CODE(HCCL_E_NETWORK), ret, qpInfo_.qpHandle, qpInfo_.retryCnt),
124 : HCCL_E_NETWORK);
125 2 : rdmaConnStatus_ = RdmaConnStatus::QP_CREATED;
126 2 : return HCCL_SUCCESS;
127 : }
128 :
129 5 : HcclResult HostRdmaConnection::DestroyQp()
130 : {
131 5 : if (rdmaConnStatus_ == RdmaConnStatus::CLOSED || rdmaConnStatus_ == RdmaConnStatus::INIT) {
132 0 : return HCCL_SUCCESS;
133 : }
134 :
135 5 : CHK_RET(Hccl::HrtRaDestroyQpWithCq(qpInfo_, isHdcMode_));
136 :
137 5 : s32 ret = RaDestroyCompChannel(qpInfo_.rdmaHandle, sendCompChannel_);
138 5 : CHK_PRT_RET(ret != 0,
139 : HCCL_ERROR("[HostRdmaConnection::DestroyQp]errNo[0x%016llx] ra_destroy_comp_channel fail. "
140 : "return[%d], params: rdmaHandle[%p], sendCompChannel[%p]",
141 : HCCL_ERROR_CODE(HCCL_E_NETWORK), ret, qpInfo_.rdmaHandle, &sendCompChannel_),
142 : HCCL_E_NETWORK);
143 4 : ret = RaDestroyCompChannel(qpInfo_.rdmaHandle, recvCompChannel_);
144 4 : CHK_PRT_RET(ret != 0,
145 : HCCL_ERROR("[HostRdmaConnection::DestroyQp]errNo[0x%016llx] ra_destroy_comp_channel fail. "
146 : "return[%d], params: rdmaHandle[%p], rcvCompChannel[%p]",
147 : HCCL_ERROR_CODE(HCCL_E_NETWORK), ret, qpInfo_.rdmaHandle, &recvCompChannel_),
148 : HCCL_E_NETWORK);
149 :
150 4 : qpInfo_ = Hccl::QpInfo();
151 4 : rdmaConnStatus_ = RdmaConnStatus::CLOSED;
152 4 : return HCCL_SUCCESS;
153 : }
154 :
155 2 : HcclResult HostRdmaConnection::GetExchangeDto(std::unique_ptr<Hccl::Serializable> &locQpAttrserial)
156 : {
157 2 : if (rdmaConnStatus_ != RdmaConnStatus::QP_CREATED && rdmaConnStatus_ != RdmaConnStatus::QP_MODIFIED) {
158 0 : HCCL_ERROR("[HostRdmaConnection][%s] status[%s] is not expected.",
159 : __func__, rdmaConnStatus_.Describe().c_str());
160 0 : return HCCL_E_AGAIN;
161 : }
162 :
163 : struct QpAttr localQpAttr;
164 2 : s32 ret = RaGetQpAttr(qpInfo_.qpHandle, &localQpAttr);
165 2 : if (ret != 0) {
166 0 : HCCL_ERROR("[HostRdmaConnection::GetExchangeDto]RaGetQpAttr failed, ret(%d)", ret);
167 0 : return HCCL_E_ROCE_CONNECT;
168 : }
169 2 : std::unique_ptr<ExchangeRdmaConnDto> dto= nullptr;
170 2 : EXCEPTION_CATCH(
171 : dto = std::make_unique<ExchangeRdmaConnDto>(localQpAttr.qpn, localQpAttr.psn, localQpAttr.gidIdx),
172 : return HCCL_E_PTR
173 : );
174 2 : CHK_SAFETY_FUNC_RET(memcpy_s(dto->gid_, HCCP_GID_RAW_LEN, localQpAttr.gid, HCCP_GID_RAW_LEN));
175 2 : locQpAttrserial = std::unique_ptr<Hccl::Serializable>(std::move(dto));
176 2 : return HCCL_SUCCESS;
177 2 : }
178 :
179 1 : HcclResult HostRdmaConnection::ParseRmtExchangeDto(const Hccl::Serializable &rmtQpAttrSerial)
180 : {
181 1 : auto dto = dynamic_cast<const ExchangeRdmaConnDto &>(rmtQpAttrSerial);
182 1 : HCCL_INFO("[HostRdmaConnection][%s] remoteConnDto[%s]", __func__, dto.Describe().c_str());
183 1 : rmtQpAttr_.psn = dto.psn_;
184 1 : rmtQpAttr_.qpn = dto.qpn_;
185 1 : rmtQpAttr_.gid_idx = dto.gid_idx_;
186 1 : CHK_SAFETY_FUNC_RET(memcpy_s(rmtQpAttr_.gid, HCCP_GID_RAW_LEN, dto.gid_, HCCP_GID_RAW_LEN));
187 1 : return HCCL_SUCCESS;
188 1 : }
189 :
190 3 : HcclResult HostRdmaConnection::ModifyQp()
191 : {
192 3 : if (rdmaConnStatus_ == RdmaConnStatus::QP_MODIFIED) {
193 0 : HCCL_WARNING("[HostRdmaConnection][%s] modify qp already, status[%s].",
194 : __func__, rdmaConnStatus_.Describe().c_str());
195 0 : return HCCL_SUCCESS;
196 : }
197 3 : if (rdmaConnStatus_ != RdmaConnStatus::QP_CREATED) {
198 0 : HCCL_ERROR("[HostRdmaConnection][%s] status[%s] is not expected.", __func__,
199 : rdmaConnStatus_.Describe().c_str());
200 0 : return HCCL_E_AGAIN;
201 : }
202 :
203 3 : if (!rmtQpAttr_.IsValid()) {
204 0 : HCCL_ERROR("[HostRdmaConnection][%s] romate Qp Attr is empty, exchange qp attr first", __func__);
205 0 : return HCCL_E_INTERNAL;
206 : }
207 :
208 : struct QpAttr localQpAttr;
209 3 : s32 ret = RaGetQpAttr(qpInfo_.qpHandle, &localQpAttr);
210 3 : if (ret != 0) {
211 0 : return HCCL_E_ROCE_CONNECT;
212 : }
213 :
214 3 : HCCL_INFO("[HostRdmaConnection::ModifyQp] HostRdmaConnection qpInfo_: serviceLevel[%d], trafficClass[%d], retryCnt[%d], retryInterval[%d]. "
215 : "roceAttr_: sl[%d], tc[%d], retryCnt[%d], retryInterval[%d]", qpInfo_.serviceLevel, qpInfo_.trafficClass, qpInfo_.retryCnt, qpInfo_.retryInterval,
216 : roceAttr_.sl, roceAttr_.tc, roceAttr_.retryCnt, roceAttr_.retryInterval);
217 3 : HCCL_DEBUG("[HostRdmaConnection::ModifyQp] HostRdmaConnection localQp: qpn[%u], psn[%u], gidIdx[%u]",
218 : localQpAttr.qpn, localQpAttr.psn, localQpAttr.gidIdx);
219 3 : HCCL_DEBUG("[HostRdmaConnection::ModifyQp] HostRdmaConnection remoteQp: qpn[%u], psn[%u], gidIdx[%u]",
220 : rmtQpAttr_.qpn, rmtQpAttr_.psn, rmtQpAttr_.gid_idx);
221 :
222 : struct TypicalQp localQp;
223 : struct TypicalQp rmtQp;
224 3 : localQp.sl = roceAttr_.sl;
225 3 : localQp.tc = roceAttr_.tc;
226 3 : localQp.retryCnt = roceAttr_.retryCnt;
227 3 : localQp.retryTime = roceAttr_.retryInterval;
228 3 : localQp.qpn = localQpAttr.qpn;
229 3 : localQp.psn = localQpAttr.psn;
230 3 : localQp.gidIdx = localQpAttr.gidIdx;
231 3 : (void)memcpy_s(localQp.gid, HCCP_GID_RAW_LEN, localQpAttr.gid, HCCP_GID_RAW_LEN);
232 3 : rmtQp.sl = qpInfo_.serviceLevel;
233 3 : rmtQp.tc = qpInfo_.trafficClass;
234 3 : rmtQp.retryCnt = qpInfo_.retryCnt;
235 3 : rmtQp.retryTime = qpInfo_.retryInterval;
236 3 : rmtQp.qpn = rmtQpAttr_.qpn;
237 3 : rmtQp.psn = rmtQpAttr_.psn;
238 3 : rmtQp.gidIdx = rmtQpAttr_.gid_idx;
239 3 : (void)memcpy_s(rmtQp.gid, HCCP_GID_RAW_LEN, rmtQpAttr_.gid, HCCP_GID_RAW_LEN);
240 3 : ret = RaTypicalQpModify(qpInfo_.qpHandle, &localQp, &rmtQp);
241 3 : if (ret != 0) {
242 0 : HCCL_ERROR("[modify][ra_qp]modify qp failed, ret(%d)", ret);
243 0 : return HCCL_E_ROCE_CONNECT;
244 : }
245 : // 调整setlbvalue到RTS状态后
246 3 : if (qpInfo_.lbValue >= 0) {
247 2 : HCCL_DEBUG("[HostRdmaConnection::ModifyQp] before RaSetQpLbValue, qp_num[%u], lbValue[%d], qpHandle[%p]",
248 : qpInfo_.qp->qp_num, qpInfo_.lbValue, qpInfo_.qpHandle);
249 2 : ret = RaSetQpLbValue(qpInfo_.qpHandle, qpInfo_.lbValue);
250 2 : CHK_PRT_RET(ret != 0,
251 : HCCL_ERROR("[HostRdmaConnection::ModifyQp][SetQpLbValue]errNo[0x%016llx] RaSetQpLbValue fail. "
252 : "return[%d], params: qpHandle[%p], lbValue[%d]",
253 : HCCL_ERROR_CODE(HCCL_E_NETWORK), ret, qpInfo_.qpHandle, qpInfo_.lbValue),
254 : HCCL_E_NETWORK);
255 : }
256 2 : rdmaConnStatus_ = RdmaConnStatus::QP_MODIFIED;
257 2 : return HCCL_SUCCESS;
258 : }
259 :
260 :
261 : } // namespace Hccl
|