Skip to content

Commit 877946d

Browse files
authored
[Feat] Add ASU SQE protocol implementations (#977)
## Purpose Implement ASU transport protocol packet builders for SQE commands and link establishment ## Modifications * Add SQE classes: Store, Retrieve, BatchStore, BatchRetrieve, Delete, Exist, KeepAlive * Add link establishment protocol: NegotiateSqe, ConnectSqe, DisconnectSqe ## Test All 11 unit tests passed (7 SQE pack + 4 link protocol pack)
1 parent 518c842 commit 877946d

6 files changed

Lines changed: 1800 additions & 0 deletions

File tree

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (c) 2026 Huawei Technologies Co., Ltd. All rights reserved.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
* */
24+
#include <cstdint>
25+
#include <cstring>
26+
#include <gtest/gtest.h>
27+
#include "link_proto.h"
28+
29+
namespace UC::ASU {
30+
namespace {
31+
32+
class LinkProtoPackTest : public ::testing::Test {
33+
protected:
34+
void SetUp() override {}
35+
void TearDown() override {}
36+
};
37+
38+
TEST_F(LinkProtoPackTest, NegotiateSqePackMatchesProtocol)
39+
{
40+
NegotiateRequest req;
41+
req.cap = 0;
42+
req.private_len = 4;
43+
req.major_version = 1;
44+
req.minor_version = 0;
45+
req.kato = 30;
46+
47+
NegotiateSqe sqe;
48+
auto status = sqe.Pack(req);
49+
ASSERT_TRUE(status.ok()) << status.message;
50+
51+
std::vector<std::uint8_t> expected(kMsgHeaderSize + kNegotiatePayloadSize, 0);
52+
53+
// Header: crc(4)=0, ver(1)=1, cmd(1)=0, pad(6)=0, len(4)=160
54+
expected[4] = 1; // ver
55+
expected[5] = 0; // cmd = Negotiate
56+
std::uint32_t payload_len = kNegotiatePayloadSize;
57+
std::memcpy(&expected[12], &payload_len, 4);
58+
59+
// Offset 16: cap[31:0] = 0
60+
// Offset 20: rsv[23:0] = 0 (already zero)
61+
// Offset 44: private_len[31:0]
62+
std::memcpy(&expected[44], &req.private_len, 4);
63+
// Offset 48: major_version
64+
expected[48] = req.major_version;
65+
// Offset 49: minor_version
66+
expected[49] = req.minor_version;
67+
// Offset 50: kato[15:0]
68+
std::memcpy(&expected[50], &req.kato, 2);
69+
70+
ASSERT_EQ(sqe.Size(), expected.size());
71+
const auto* packed = static_cast<const std::uint8_t*>(sqe.Data());
72+
for (std::size_t i = 0; i < expected.size(); ++i) {
73+
EXPECT_EQ(packed[i], expected[i])
74+
<< "Mismatch at byte " << i << ": expected 0x" << std::hex
75+
<< static_cast<int>(expected[i]) << ", got 0x" << static_cast<int>(packed[i]);
76+
}
77+
}
78+
79+
TEST_F(LinkProtoPackTest, HandshakeSqePackMatchesProtocol)
80+
{
81+
HandshakeRequest req;
82+
for (int i = 0; i < 16; ++i) { req.gid[i] = static_cast<std::uint8_t>(0xA0 + i); }
83+
req.lid = 0x1234;
84+
req.mtu = 4; // 2048 bytes
85+
req.total_qp_num = 8;
86+
req.sl = 1;
87+
req.traffic_class = 2;
88+
req.rnr_timer = 3;
89+
req.rnr_retry_cnt = 7;
90+
req.timeout = 14;
91+
req.retry_cnt = 5;
92+
req.qp_rd_atom = 6;
93+
req.rsv = 0;
94+
req.start_psn = 0xDEADBEEF;
95+
for (int i = 0; i < 32; ++i) { req.qpn[i] = 0x1000 + i; }
96+
97+
HandshakeSqe sqe;
98+
auto status = sqe.Pack(req);
99+
ASSERT_TRUE(status.ok()) << status.message;
100+
101+
std::vector<std::uint8_t> expected(kMsgHeaderSize + kHandshakePayloadSize, 0);
102+
103+
// Header: crc(4)=0, ver(1)=1, cmd(1)=1, pad(6)=0, len(4)=160
104+
expected[4] = 1; // ver
105+
expected[5] = 1; // cmd = Handshake
106+
std::uint32_t payload_len = kHandshakePayloadSize;
107+
std::memcpy(&expected[12], &payload_len, 4);
108+
109+
// Offset 16: gid[15:0]
110+
std::memcpy(&expected[16], req.gid, 16);
111+
// Offset 32: lid[15:0]
112+
std::memcpy(&expected[32], &req.lid, 2);
113+
// Offset 34: mtu
114+
expected[34] = req.mtu;
115+
// Offset 35: total_qp_num
116+
expected[35] = req.total_qp_num;
117+
// Offset 36: sl
118+
expected[36] = req.sl;
119+
// Offset 37: traffic_class
120+
expected[37] = req.traffic_class;
121+
// Offset 38: rnr_timer
122+
expected[38] = req.rnr_timer;
123+
// Offset 39: rnr_retry_cnt
124+
expected[39] = req.rnr_retry_cnt;
125+
// Offset 40: timeout
126+
expected[40] = req.timeout;
127+
// Offset 41: retry_cnt
128+
expected[41] = req.retry_cnt;
129+
// Offset 42: qp_rd_atom
130+
expected[42] = req.qp_rd_atom;
131+
// Offset 43: rsv
132+
expected[43] = req.rsv;
133+
// Offset 44: start_psn[31:0]
134+
std::memcpy(&expected[44], &req.start_psn, 4);
135+
// Offset 48: qpn[32] (128 bytes)
136+
std::memcpy(&expected[48], req.qpn, 128);
137+
138+
ASSERT_EQ(sqe.Size(), expected.size());
139+
const auto* packed = static_cast<const std::uint8_t*>(sqe.Data());
140+
for (std::size_t i = 0; i < expected.size(); ++i) {
141+
EXPECT_EQ(packed[i], expected[i])
142+
<< "Mismatch at byte " << i << ": expected 0x" << std::hex
143+
<< static_cast<int>(expected[i]) << ", got 0x" << static_cast<int>(packed[i]);
144+
}
145+
}
146+
147+
TEST_F(LinkProtoPackTest, HandshakeDoneSqePackMatchesProtocol)
148+
{
149+
HandshakeDoneSqe sqe;
150+
auto status = sqe.Pack();
151+
ASSERT_TRUE(status.ok()) << status.message;
152+
153+
std::vector<std::uint8_t> expected(kMsgHeaderSize, 0);
154+
155+
// Header: crc(4)=0, ver(1)=1, cmd(1)=3, pad(6)=0, len(4)=0
156+
expected[4] = 1; // ver
157+
expected[5] = 3; // cmd = HandshakeDone
158+
std::uint32_t payload_len = 0;
159+
std::memcpy(&expected[12], &payload_len, 4);
160+
161+
ASSERT_EQ(sqe.Size(), expected.size());
162+
const auto* packed = static_cast<const std::uint8_t*>(sqe.Data());
163+
for (std::size_t i = 0; i < expected.size(); ++i) {
164+
EXPECT_EQ(packed[i], expected[i])
165+
<< "Mismatch at byte " << i << ": expected 0x" << std::hex
166+
<< static_cast<int>(expected[i]) << ", got 0x" << static_cast<int>(packed[i]);
167+
}
168+
}
169+
170+
TEST_F(LinkProtoPackTest, DisconnectSqePackMatchesProtocol)
171+
{
172+
DisconnectRequest req;
173+
req.local_qpn = 0x00010001;
174+
req.remote_qpn = 0x00020002;
175+
176+
DisconnectSqe sqe;
177+
auto status = sqe.Pack(req);
178+
ASSERT_TRUE(status.ok()) << status.message;
179+
180+
std::vector<std::uint8_t> expected(kMsgHeaderSize + kDisconnectPayloadSize, 0);
181+
182+
// Header: crc(4)=0, ver(1)=1, cmd(1)=4, pad(6)=0, len(4)=8
183+
expected[4] = 1; // ver
184+
expected[5] = 4; // cmd = Disconnect
185+
std::uint32_t payload_len = kDisconnectPayloadSize;
186+
std::memcpy(&expected[12], &payload_len, 4);
187+
188+
// Offset 16: local_qpn[31:0]
189+
std::memcpy(&expected[16], &req.local_qpn, 4);
190+
// Offset 20: remote_qpn[31:0]
191+
std::memcpy(&expected[20], &req.remote_qpn, 4);
192+
193+
ASSERT_EQ(sqe.Size(), expected.size());
194+
const auto* packed = static_cast<const std::uint8_t*>(sqe.Data());
195+
for (std::size_t i = 0; i < expected.size(); ++i) {
196+
EXPECT_EQ(packed[i], expected[i])
197+
<< "Mismatch at byte " << i << ": expected 0x" << std::hex
198+
<< static_cast<int>(expected[i]) << ", got 0x" << static_cast<int>(packed[i]);
199+
}
200+
}
201+
202+
} // namespace
203+
} // namespace UC::ASU

0 commit comments

Comments
 (0)