Skip to content

Commit 4603f83

Browse files
authored
Merge pull request #1580 from ddmatsu/odp-extended
RDMA FLUSH and ATOMIC WRITE with ODP
2 parents b837a74 + 968e842 commit 4603f83

File tree

9 files changed

+160
-58
lines changed

9 files changed

+160
-58
lines changed

kernel-headers/rdma/ib_user_verbs.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,22 @@ struct ib_uverbs_ex_query_device {
233233
__u32 reserved;
234234
};
235235

236+
enum ib_uverbs_odp_general_cap_bits {
237+
IB_UVERBS_ODP_SUPPORT = 1 << 0,
238+
IB_UVERBS_ODP_SUPPORT_IMPLICIT = 1 << 1,
239+
};
240+
241+
enum ib_uverbs_odp_transport_cap_bits {
242+
IB_UVERBS_ODP_SUPPORT_SEND = 1 << 0,
243+
IB_UVERBS_ODP_SUPPORT_RECV = 1 << 1,
244+
IB_UVERBS_ODP_SUPPORT_WRITE = 1 << 2,
245+
IB_UVERBS_ODP_SUPPORT_READ = 1 << 3,
246+
IB_UVERBS_ODP_SUPPORT_ATOMIC = 1 << 4,
247+
IB_UVERBS_ODP_SUPPORT_SRQ_RECV = 1 << 5,
248+
IB_UVERBS_ODP_SUPPORT_FLUSH = 1 << 6,
249+
IB_UVERBS_ODP_SUPPORT_ATOMIC_WRITE = 1 << 7,
250+
};
251+
236252
struct ib_uverbs_odp_caps {
237253
__aligned_u64 general_caps;
238254
struct {

libibverbs/examples/devinfo.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,9 @@ static void print_odp_trans_caps(uint32_t trans)
330330
IBV_ODP_SUPPORT_WRITE |
331331
IBV_ODP_SUPPORT_READ |
332332
IBV_ODP_SUPPORT_ATOMIC |
333-
IBV_ODP_SUPPORT_SRQ_RECV);
333+
IBV_ODP_SUPPORT_SRQ_RECV |
334+
IBV_ODP_SUPPORT_FLUSH |
335+
IBV_ODP_SUPPORT_ATOMIC_WRITE);
334336

335337
if (!trans) {
336338
printf("\t\t\t\t\tNO SUPPORT\n");
@@ -347,6 +349,10 @@ static void print_odp_trans_caps(uint32_t trans)
347349
printf("\t\t\t\t\tSUPPORT_ATOMIC\n");
348350
if (trans & IBV_ODP_SUPPORT_SRQ_RECV)
349351
printf("\t\t\t\t\tSUPPORT_SRQ\n");
352+
if (trans & IBV_ODP_SUPPORT_FLUSH)
353+
printf("\t\t\t\t\tSUPPORT_FLUSH\n");
354+
if (trans & IBV_ODP_SUPPORT_ATOMIC_WRITE)
355+
printf("\t\t\t\t\tSUPPORT_ATOMIC_WRITE\n");
350356
if (trans & unknown_transport_caps)
351357
printf("\t\t\t\t\tUnknown flags: 0x%" PRIX32 "\n",
352358
trans & unknown_transport_caps);

libibverbs/man/ibv_query_device_ex.3

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ enum ibv_odp_transport_cap_bits {
6868
IBV_ODP_SUPPORT_READ = 1 << 3, /* RDMA-Read operations support on-demand paging */
6969
IBV_ODP_SUPPORT_ATOMIC = 1 << 4, /* RDMA-Atomic operations support on-demand paging */
7070
IBV_ODP_SUPPORT_SRQ_RECV = 1 << 5, /* SRQ receive operations support on-demand paging */
71+
IBV_ODP_SUPPORT_FLUSH = 1 << 6, /* RDMA-Flush operations support on-demand paging */
72+
IBV_ODP_SUPPORT_ATOMIC_WRITE = 1 << 7, /* RDMA-Atomic-write operations support on-demand paing */
7173
};
7274

7375
struct ibv_tso_caps {

libibverbs/verbs.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,20 @@ struct ibv_query_device_ex_input {
228228
uint32_t comp_mask;
229229
};
230230

231+
enum ibv_odp_general_caps {
232+
IBV_ODP_SUPPORT = 1 << 0,
233+
IBV_ODP_SUPPORT_IMPLICIT = 1 << 1,
234+
};
235+
231236
enum ibv_odp_transport_cap_bits {
232237
IBV_ODP_SUPPORT_SEND = 1 << 0,
233238
IBV_ODP_SUPPORT_RECV = 1 << 1,
234239
IBV_ODP_SUPPORT_WRITE = 1 << 2,
235240
IBV_ODP_SUPPORT_READ = 1 << 3,
236241
IBV_ODP_SUPPORT_ATOMIC = 1 << 4,
237242
IBV_ODP_SUPPORT_SRQ_RECV = 1 << 5,
243+
IBV_ODP_SUPPORT_FLUSH = 1 << 6,
244+
IBV_ODP_SUPPORT_ATOMIC_WRITE = 1 << 7,
238245
};
239246

240247
struct ibv_odp_caps {
@@ -246,11 +253,6 @@ struct ibv_odp_caps {
246253
} per_transport_caps;
247254
};
248255

249-
enum ibv_odp_general_caps {
250-
IBV_ODP_SUPPORT = 1 << 0,
251-
IBV_ODP_SUPPORT_IMPLICIT = 1 << 1,
252-
};
253-
254256
struct ibv_tso_caps {
255257
uint32_t max_tso;
256258
uint32_t supported_qpts;

pyverbs/device.pyx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,9 @@ cdef class ODPCaps(PyverbsObject):
567567
e.IBV_ODP_SUPPORT_WRITE: 'IBV_ODP_SUPPORT_WRITE',
568568
e.IBV_ODP_SUPPORT_READ: 'IBV_ODP_SUPPORT_READ',
569569
e.IBV_ODP_SUPPORT_ATOMIC: 'IBV_ODP_SUPPORT_ATOMIC',
570-
e.IBV_ODP_SUPPORT_SRQ_RECV: 'IBV_ODP_SUPPORT_SRQ_RECV'}
570+
e.IBV_ODP_SUPPORT_SRQ_RECV: 'IBV_ODP_SUPPORT_SRQ_RECV',
571+
e.IBV_ODP_SUPPORT_FLUSH: 'IBV_ODP_SUPPORT_FLUSH',
572+
e.IBV_ODP_SUPPORT_ATOMIC_WRITE: 'IBV_ODP_SUPPORT_ATOMIC_WRITE'}
571573

572574
print_format = '{}: {}\n'
573575
return print_format.format('ODP General caps', str_from_flags(self.general_caps, general_caps)) +\

pyverbs/libibverbs_enums.pxd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ cdef extern from '<infiniband/verbs.h>':
417417
IBV_ODP_SUPPORT_READ
418418
IBV_ODP_SUPPORT_ATOMIC
419419
IBV_ODP_SUPPORT_SRQ_RECV
420+
IBV_ODP_SUPPORT_FLUSH
421+
IBV_ODP_SUPPORT_ATOMIC_WRITE
420422

421423
cpdef enum ibv_device_cap_flags:
422424
IBV_DEVICE_RESIZE_MAX_WR

tests/test_odp.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from pyverbs.mr import MR
88
import pyverbs.enums as e
99
import tests.utils as u
10+
import unittest
1011

1112
HUGE_PAGE_SIZE = 0x200000
1213

@@ -112,6 +113,56 @@ def create_mr(self):
112113
flags=MAP_ANONYMOUS_| MAP_PRIVATE_)
113114
self.mr = u.create_custom_mr(self, e.IBV_ACCESS_ON_DEMAND, user_addr=self.user_addr)
114115

116+
class OdpQpExRC(RCResources):
117+
def __init__(self, dev_name, ib_port, gid_index, is_huge=False,
118+
request_user_addr=False, use_mr_prefetch=None, is_implicit=False,
119+
prefetch_advice=e._IBV_ADVISE_MR_ADVICE_PREFETCH_WRITE,
120+
msg_size=8, odp_caps=e.IBV_ODP_SUPPORT_SEND | e.IBV_ODP_SUPPORT_RECV,
121+
use_mixed_mr=False):
122+
123+
''' For object descriptions, refer to OdpRC class '''
124+
self.request_user_addr = request_user_addr
125+
self.is_implicit = is_implicit
126+
self.odp_caps = odp_caps
127+
self.access = e.IBV_ACCESS_LOCAL_WRITE | e.IBV_ACCESS_ON_DEMAND | \
128+
e.IBV_ACCESS_REMOTE_ATOMIC | e.IBV_ACCESS_REMOTE_READ | \
129+
e.IBV_ACCESS_REMOTE_WRITE
130+
self.user_addr = None
131+
super(OdpQpExRC, self).__init__(dev_name=dev_name, ib_port=ib_port,
132+
gid_index=gid_index)
133+
self.msg_size = msg_size
134+
135+
if self.odp_caps & e.IBV_ODP_SUPPORT_FLUSH:
136+
self.ptype = e.IBV_FLUSH_GLOBAL
137+
self.level = e.IBV_FLUSH_RANGE
138+
139+
def create_qps(self):
140+
if self.odp_caps & e.IBV_ODP_SUPPORT_ATOMIC_WRITE:
141+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_ATOMIC_WRITE)
142+
elif self.odp_caps & e.IBV_ODP_SUPPORT_FLUSH:
143+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_FLUSH | e.IBV_QP_EX_WITH_RDMA_WRITE)
144+
else:
145+
raise unittest.SkipTest('There is no qpex test for the specified ODP caps.')
146+
147+
def create_mr(self):
148+
u.odp_supported(self.ctx, 'rc', self.odp_caps)
149+
if self.odp_caps & e.IBV_ODP_SUPPORT_ATOMIC_WRITE:
150+
access = self.access
151+
if self.request_user_addr:
152+
mmap_flags = MAP_ANONYMOUS_| MAP_PRIVATE_
153+
length = self.msg_size
154+
self.user_addr = mmap(length=length, flags=mmap_flags)
155+
self.mr = MR(self.pd, self.msg_size, access, address=self.user_addr,
156+
implicit=self.is_implicit)
157+
elif self.odp_caps & e.IBV_ODP_SUPPORT_FLUSH:
158+
try:
159+
self.mr = u.create_custom_mr(self, e.IBV_ACCESS_FLUSH_GLOBAL | e.IBV_ACCESS_REMOTE_WRITE | e.IBV_ACCESS_ON_DEMAND)
160+
except PyverbsRDMAError as ex:
161+
if ex.error_code == errno.EINVAL:
162+
raise unittest.SkipTest('Create mr with IBV_ACCESS_FLUSH_GLOBAL access flag is not supported in kernel')
163+
raise ex
164+
else:
165+
raise unittest.SkipTest('There is no qpex test for the specified ODP caps.')
115166

116167
class OdpTestCase(RDMATestCase):
117168
def setUp(self):
@@ -150,6 +201,28 @@ def test_odp_rc_mixed_mr(self):
150201
use_mixed_mr=True)
151202
u.traffic(**self.traffic_args)
152203

204+
def test_odp_qp_ex_rc_atomic_write(self):
205+
super().create_players(OdpQpExRC, request_user_addr=self.force_page_faults,
206+
msg_size=8, odp_caps=e.IBV_ODP_SUPPORT_ATOMIC_WRITE)
207+
self.client.msg_size = 8
208+
self.server.msg_size = 8
209+
u.rdma_traffic(**self.traffic_args,
210+
new_send=True, send_op=e.IBV_WR_ATOMIC_WRITE)
211+
212+
def test_odp_qp_ex_rc_flush(self):
213+
super().create_players(OdpQpExRC, request_user_addr=self.force_page_faults,
214+
odp_caps=e.IBV_ODP_SUPPORT_FLUSH)
215+
wcs = u.flush_traffic(**self.traffic_args, new_send=True,
216+
send_op=e.IBV_WR_FLUSH)
217+
if wcs[0].status != e.IBV_WC_SUCCESS:
218+
raise PyverbsError(f'Unexpected {wc_status_to_str(wcs[0].status)}')
219+
220+
self.client.level = e.IBV_FLUSH_MR
221+
wcs = u.flush_traffic(**self.traffic_args, new_send=True,
222+
send_op=e.IBV_WR_FLUSH)
223+
if wcs[0].status != e.IBV_WC_SUCCESS:
224+
raise PyverbsError(f'Unexpected {wc_status_to_str(wcs[0].status)}')
225+
153226
def test_odp_rc_atomic_cmp_and_swp(self):
154227
self.create_players(OdpRC, request_user_addr=self.force_page_faults,
155228
msg_size=8, odp_caps=e.IBV_ODP_SUPPORT_ATOMIC)

tests/test_qpex.py

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,14 @@
1212
from tests.base import UDResources, RCResources, RDMATestCase, XRCResources
1313
import tests.utils as u
1414

15-
16-
def create_qp_ex(agr_obj, qp_type, send_flags):
17-
if qp_type == e.IBV_QPT_XRC_SEND:
18-
cap = QPCap(max_send_wr=agr_obj.num_msgs, max_recv_wr=0, max_recv_sge=0,
19-
max_send_sge=1)
20-
else:
21-
cap = QPCap(max_send_wr=agr_obj.num_msgs, max_recv_wr=agr_obj.num_msgs,
22-
max_recv_sge=1, max_send_sge=1)
23-
qia = QPInitAttrEx(cap=cap, qp_type=qp_type, scq=agr_obj.cq,
24-
rcq=agr_obj.cq, pd=agr_obj.pd, send_ops_flags=send_flags,
25-
comp_mask=e.IBV_QP_INIT_ATTR_PD |
26-
e.IBV_QP_INIT_ATTR_SEND_OPS_FLAGS)
27-
qp_attr = QPAttr(port_num=agr_obj.ib_port)
28-
if qp_type == e.IBV_QPT_UD:
29-
qp_attr.qkey = agr_obj.UD_QKEY
30-
qp_attr.pkey_index = agr_obj.UD_PKEY_INDEX
31-
if qp_type == e.IBV_QPT_RC:
32-
qp_attr.qp_access_flags = e.IBV_ACCESS_REMOTE_WRITE | \
33-
e.IBV_ACCESS_REMOTE_READ | \
34-
e.IBV_ACCESS_REMOTE_ATOMIC | \
35-
e.IBV_ACCESS_FLUSH_GLOBAL | \
36-
e.IBV_ACCESS_FLUSH_PERSISTENT
37-
try:
38-
# We don't have capability bits for this
39-
qp = QPEx(agr_obj.ctx, qia, qp_attr)
40-
except PyverbsRDMAError as ex:
41-
if ex.error_code == errno.EOPNOTSUPP:
42-
raise unittest.SkipTest('Extended QP is not supported on this device')
43-
raise ex
44-
if qp_type != e.IBV_QPT_XRC_SEND:
45-
agr_obj.qps.append(qp)
46-
agr_obj.qps_num.append(qp.qp_num)
47-
agr_obj.psns.append(random.getrandbits(24))
48-
else:
49-
return qp
50-
51-
5215
class QpExUDSend(UDResources):
5316
def create_qps(self):
54-
create_qp_ex(self, e.IBV_QPT_UD, e.IBV_QP_EX_WITH_SEND)
17+
u.create_qp_ex(self, e.IBV_QPT_UD, e.IBV_QP_EX_WITH_SEND)
5518

5619

5720
class QpExRCSend(RCResources):
5821
def create_qps(self):
59-
create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_SEND)
22+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_SEND)
6023

6124

6225
class QpExXRCSend(XRCResources):
@@ -72,20 +35,20 @@ def create_qps(self):
7235
recv_qp = QP(self.ctx, attr_ex, qp_attr)
7336
self.rqp_lst.append(recv_qp)
7437

75-
send_qp = create_qp_ex(self, e.IBV_QPT_XRC_SEND, e.IBV_QP_EX_WITH_SEND)
38+
send_qp = u.create_qp_ex(self, e.IBV_QPT_XRC_SEND, e.IBV_QP_EX_WITH_SEND)
7639
self.sqp_lst.append(send_qp)
7740
self.qps_num.append((recv_qp.qp_num, send_qp.qp_num))
7841
self.psns.append(random.getrandbits(24))
7942

8043

8144
class QpExUDSendImm(UDResources):
8245
def create_qps(self):
83-
create_qp_ex(self, e.IBV_QPT_UD, e.IBV_QP_EX_WITH_SEND_WITH_IMM)
46+
u.create_qp_ex(self, e.IBV_QPT_UD, e.IBV_QP_EX_WITH_SEND_WITH_IMM)
8447

8548

8649
class QpExRCSendImm(RCResources):
8750
def create_qps(self):
88-
create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_SEND_WITH_IMM)
51+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_SEND_WITH_IMM)
8952

9053

9154
class QpExXRCSendImm(XRCResources):
@@ -101,7 +64,7 @@ def create_qps(self):
10164
recv_qp = QP(self.ctx, attr_ex, qp_attr)
10265
self.rqp_lst.append(recv_qp)
10366

104-
send_qp = create_qp_ex(self, e.IBV_QPT_XRC_SEND,
67+
send_qp = u.create_qp_ex(self, e.IBV_QPT_XRC_SEND,
10568
e.IBV_QP_EX_WITH_SEND_WITH_IMM)
10669
self.sqp_lst.append(send_qp)
10770
self.qps_num.append((recv_qp.qp_num, send_qp.qp_num))
@@ -112,7 +75,7 @@ class QpExRCFlush(RCResources):
11275
ptype = e.IBV_FLUSH_GLOBAL
11376
level = e.IBV_FLUSH_RANGE
11477
def create_qps(self):
115-
create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_FLUSH | e.IBV_QP_EX_WITH_RDMA_WRITE)
78+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_FLUSH | e.IBV_QP_EX_WITH_RDMA_WRITE)
11679

11780
def create_mr(self):
11881
try:
@@ -125,23 +88,23 @@ def create_mr(self):
12588

12689
class QpExRCAtomicWrite(RCResources):
12790
def create_qps(self):
128-
create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_ATOMIC_WRITE)
91+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_ATOMIC_WRITE)
12992

13093
def create_mr(self):
13194
self.mr = u.create_custom_mr(self, e.IBV_ACCESS_REMOTE_WRITE)
13295

13396

13497
class QpExRCRDMAWrite(RCResources):
13598
def create_qps(self):
136-
create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_RDMA_WRITE)
99+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_RDMA_WRITE)
137100

138101
def create_mr(self):
139102
self.mr = u.create_custom_mr(self, e.IBV_ACCESS_REMOTE_WRITE)
140103

141104

142105
class QpExRCRDMAWriteImm(RCResources):
143106
def create_qps(self):
144-
create_qp_ex(self, e.IBV_QPT_RC,
107+
u.create_qp_ex(self, e.IBV_QPT_RC,
145108
e.IBV_QP_EX_WITH_RDMA_WRITE_WITH_IMM)
146109

147110
def create_mr(self):
@@ -150,29 +113,29 @@ def create_mr(self):
150113

151114
class QpExRCRDMARead(RCResources):
152115
def create_qps(self):
153-
create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_RDMA_READ)
116+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_RDMA_READ)
154117

155118
def create_mr(self):
156119
self.mr = u.create_custom_mr(self, e.IBV_ACCESS_REMOTE_READ)
157120

158121

159122
class QpExRCAtomicCmpSwp(RCResources):
160123
def create_qps(self):
161-
create_qp_ex(self, e.IBV_QPT_RC,
124+
u.create_qp_ex(self, e.IBV_QPT_RC,
162125
e.IBV_QP_EX_WITH_ATOMIC_CMP_AND_SWP)
163126
self.mr = u.create_custom_mr(self, e.IBV_ACCESS_REMOTE_ATOMIC)
164127

165128

166129
class QpExRCAtomicFetchAdd(RCResources):
167130
def create_qps(self):
168-
create_qp_ex(self, e.IBV_QPT_RC,
131+
u.create_qp_ex(self, e.IBV_QPT_RC,
169132
e.IBV_QP_EX_WITH_ATOMIC_FETCH_AND_ADD)
170133
self.mr = u.create_custom_mr(self, e.IBV_ACCESS_REMOTE_ATOMIC)
171134

172135

173136
class QpExRCBindMw(RCResources):
174137
def create_qps(self):
175-
create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_RDMA_WRITE |
138+
u.create_qp_ex(self, e.IBV_QPT_RC, e.IBV_QP_EX_WITH_RDMA_WRITE |
176139
e.IBV_QP_EX_WITH_BIND_MW)
177140

178141
def create_mr(self):

0 commit comments

Comments
 (0)