blob: 58b3855240f67290055f8778622c39fdd9412c6f [file] [log] [blame]
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001/**
2 * Copyright (C) 2016 Mellanox Technologies Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#ifndef __IBVT_ENV_H_
30#define __IBVT_ENV_H_
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include <inttypes.h>
37#include <signal.h>
Artemy Kovalyov36eea222017-10-04 01:27:27 +030038#define __STDC_LIMIT_MACROS
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +030039#include <stdint.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <sys/mman.h>
44#include <sys/time.h>
45#include <sys/types.h>
46#include <unistd.h>
Artemy Kovalyovc0206e62017-09-13 13:34:04 +030047#include <dirent.h>
Artemy Kovalyov207d0742016-09-13 12:54:47 +030048#include <linux/limits.h>
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +030049
50#include <infiniband/verbs.h>
51
Artemy Kovalyov441bd412018-02-24 20:55:49 +020052#if HAVE_INFINIBAND_VERBS_EXP_H
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +030053#include <infiniband/verbs_exp.h>
54
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +020055#define ibv_flow_attr ibv_exp_flow_attr
56#define ibv_flow_spec_eth ibv_exp_flow_spec_eth
57#define ibv_flow ibv_exp_flow
58#define ibv_flow_attr ibv_exp_flow_attr
59#define ibv_create_flow ibv_exp_create_flow
60#define ibv_destroy_flow ibv_exp_destroy_flow
61#define ibv_flow_attr ibv_exp_flow_attr
62#define ibv_flow_spec ibv_exp_flow_spec
63#define ibv_flow_attr ibv_exp_flow_attr
64#define ibv_flow_spec_tunnel ibv_exp_flow_spec_tunnel
65#define ibv_flow_spec_eth ibv_exp_flow_spec_eth
66#define ibv_flow_spec_ipv4 ibv_exp_flow_spec_ipv4
67#define ibv_flow_spec_tcp_udp ibv_exp_flow_spec_tcp_udp
68#define ibv_flow_attr ibv_exp_flow_attr
69#define IBV_FLOW_ATTR_NORMAL IBV_EXP_FLOW_ATTR_NORMAL
70#define ibv_flow_attr ibv_exp_flow_attr
71#define ibv_flow_spec ibv_exp_flow_spec
72#define IBV_FLOW_SPEC_ETH IBV_EXP_FLOW_SPEC_ETH
73#define ibv_flow_spec_eth ibv_exp_flow_spec_eth
74#define IBV_FLOW_SPEC_IPV4 IBV_EXP_FLOW_SPEC_IPV4
75#define IBV_FLOW_SPEC_UDP IBV_EXP_FLOW_SPEC_UDP
76#define IBV_FLOW_SPEC_VXLAN_TUNNEL IBV_EXP_FLOW_SPEC_VXLAN_TUNNEL
77#define ibv_flow_spec_tunnel ibv_exp_flow_spec_tunnel
78#define IBV_FLOW_SPEC_INNER IBV_EXP_FLOW_SPEC_INNER
79#define ibv_flow ibv_exp_flow
80#define ibv_flow_spec_type ibv_exp_flow_spec_type
Moses Reuben06b0ac52016-12-15 11:15:09 -050081
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +020082#define IBV_FLOW_SPEC_ACTION_TAG IBV_EXP_FLOW_SPEC_ACTION_TAG
83#define ibv_flow_spec_action_tag ibv_exp_flow_spec_action_tag
Moses Reuben520ff652017-01-05 09:57:18 +000084
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +020085#define ibv_peer_commit ibv_exp_peer_commit
86#define ibv_peer_commit_qp ibv_exp_peer_commit_qp
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +030087
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +020088#define ibv_create_qp_ex ibv_exp_create_qp
89#define ibv_qp_init_attr_ex ibv_exp_qp_init_attr
90#define ibv_create_cq_attr_ex ibv_exp_cq_init_attr
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +030091
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +020092#define IBV_QP_INIT_ATTR_PD IBV_EXP_QP_INIT_ATTR_PD
93#define IBV_QP_INIT_ATTR_PEER_DIRECT IBV_EXP_QP_INIT_ATTR_PEER_DIRECT
94#define IBV_CREATE_CQ_ATTR_PEER_DIRECT IBV_EXP_CQ_INIT_ATTR_PEER_DIRECT
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +030095
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +020096#define IBV_PEER_OP_FENCE IBV_EXP_PEER_OP_FENCE
97#define IBV_PEER_OP_STORE_DWORD IBV_EXP_PEER_OP_STORE_DWORD
98#define IBV_PEER_OP_STORE_QWORD IBV_EXP_PEER_OP_STORE_QWORD
99#define IBV_PEER_OP_POLL_AND_DWORD IBV_EXP_PEER_OP_POLL_AND_DWORD
100#define IBV_PEER_OP_POLL_NOR_DWORD IBV_EXP_PEER_OP_POLL_NOR_DWORD
101#define IBV_PEER_OP_POLL_GEQ_DWORD IBV_EXP_PEER_OP_POLL_NOR_DWORD
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300102
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +0200103#define IBV_PEER_OP_FENCE_CAP IBV_EXP_PEER_OP_FENCE_CAP
104#define IBV_PEER_OP_STORE_DWORD_CAP IBV_EXP_PEER_OP_STORE_DWORD_CAP
105#define IBV_PEER_OP_STORE_QWORD_CAP IBV_EXP_PEER_OP_STORE_QWORD_CAP
106#define IBV_PEER_OP_POLL_AND_DWORD_CAP IBV_EXP_PEER_OP_POLL_AND_DWORD_CAP
107#define IBV_PEER_OP_POLL_NOR_DWORD_CAP IBV_EXP_PEER_OP_POLL_NOR_DWORD_CAP
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300108
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +0200109#define IBV_PEER_FENCE_CPU_TO_HCA IBV_EXP_PEER_FENCE_CPU_TO_HCA
110#define IBV_PEER_FENCE_PEER_TO_HCA IBV_EXP_PEER_FENCE_PEER_TO_HCA
111#define IBV_PEER_FENCE_PEER_TO_CPU IBV_EXP_PEER_FENCE_PEER_TO_CPU
112#define IBV_PEER_FENCE_HCA_TO_PEER IBV_EXP_PEER_FENCE_HCA_TO_PEER
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300113
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +0200114#define ibv_peer_direct_attr ibv_exp_peer_direct_attr
115#define ibv_peer_direction ibv_exp_peer_direction
116#define ibv_peer_op ibv_exp_peer_op
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300117
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +0200118#define IBV_ROLLBACK_ABORT_UNCOMMITED IBV_EXP_ROLLBACK_ABORT_UNCOMMITED
119#define IBV_ROLLBACK_ABORT_LATE IBV_EXP_ROLLBACK_ABORT_LATE
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300120
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +0200121#define ibv_rollback_ctx ibv_exp_rollback_ctx
122#define ibv_rollback_qp ibv_exp_rollback_qp
123#define ibv_peer_peek ibv_exp_peer_peek
124#define ibv_peer_peek_cq ibv_exp_peer_peek_cq
125#define ibv_peer_abort_peek ibv_exp_peer_abort_peek
126#define ibv_peer_abort_peek_cq ibv_exp_peer_abort_peek_cq
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300127
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +0200128#define IBV_PEER_DIRECTION_FROM_CPU IBV_EXP_PEER_DIRECTION_FROM_CPU
129#define IBV_PEER_DIRECTION_FROM_HCA IBV_EXP_PEER_DIRECTION_FROM_HCA
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300130
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +0200131#define ibv_peer_buf ibv_exp_peer_buf
132#define ibv_peer_buf_alloc_attr ibv_exp_peer_buf_alloc_attr
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300133#define IBV_SEND_SIGNALED IBV_EXP_SEND_SIGNALED
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300134
135#define ibv_create_cq_ex_(ctx, attr, n, ch) \
136 ibv_exp_create_cq(ctx, n, NULL, ch, 0, attr)
137
Artemy Kovalyovb78f6de2016-08-30 17:41:21 +0300138#define ibv_device_attr_ex ibv_exp_device_attr
Artemy Kovalyovfc18a362018-12-12 10:07:23 +0200139#if HAVE_DECL_IBV_EXP_DEVICE_ATTR_RESERVED_2
140# define SET_DEVICE_ATTR_COMP_MASK(attr) \
141 (attr)->comp_mask = 0xffffffff; \
142 (attr)->comp_mask_2 = IBV_EXP_DEVICE_ATTR_RESERVED_2 - 1;
143#else
144# define SET_DEVICE_ATTR_COMP_MASK(attr) \
145 (attr)->comp_mask = IBV_EXP_DEVICE_ATTR_RESERVED - 1;
146#endif
Artemy Kovalyovb78f6de2016-08-30 17:41:21 +0300147#define ibv_query_device_(ctx, attr, attr2) ({ \
Artemy Kovalyova5bfe6f2018-06-03 17:25:12 +0300148 int ret; \
Artemy Kovalyovfc18a362018-12-12 10:07:23 +0200149 SET_DEVICE_ATTR_COMP_MASK(attr) \
Artemy Kovalyova5bfe6f2018-06-03 17:25:12 +0300150 ret = ibv_exp_query_device(ctx, attr); \
Artemy Kovalyovb78f6de2016-08-30 17:41:21 +0300151 attr2 = (typeof attr2)(attr); ret ; })
152
153#define IBV_ACCESS_ON_DEMAND IBV_EXP_ACCESS_ON_DEMAND
154
155#define ibv_reg_mr(p, a, len, access) ({ \
156 struct ibv_exp_reg_mr_in in; \
157 in.pd = p; \
158 in.addr = a; \
159 in.length = len; \
160 in.exp_access = access; \
161 in.comp_mask = 0; \
162 ibv_exp_reg_mr(&in); })
163
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300164
165#define ibv_srq_init_attr_ex ibv_exp_create_srq_attr
166#define ibv_create_srq_ex ibv_exp_create_srq
167#define ibv_dct ibv_exp_dct
168
169#define IBV_WR_SEND IBV_EXP_WR_SEND
170#define IBV_WR_RDMA_READ IBV_EXP_WR_RDMA_READ
171#define IBV_WR_RDMA_WRITE IBV_EXP_WR_RDMA_WRITE
172#define ibv_wr_opcode ibv_exp_wr_opcode
173#define ibv_send_flags ibv_exp_send_flags
174#define _wr_opcode exp_opcode
175#define _wr_send_flags exp_send_flags
176#define ibv_post_send ibv_exp_post_send
177#define ibv_send_wr ibv_exp_send_wr
178
Artemy Kovalyovfaf40a52017-07-15 12:30:50 +0300179#define ibv_wc ibv_exp_wc
180#define ibv_poll_cq(a,b,c) ibv_exp_poll_cq(a,b,c,sizeof(*(c)))
181#define ibv_wc_opcode ibv_exp_wc_opcode
182#define _wc_opcode exp_opcode
183#define wc_flags exp_wc_flags
Artemy Kovalyova5bfe6f2018-06-03 17:25:12 +0300184#define IBV_ODP_SUPPORT_IMPLICIT IBV_EXP_ODP_SUPPORT_IMPLICIT
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300185#else
186
Artemy Kovalyova5bfe6f2018-06-03 17:25:12 +0300187#define general_odp_caps general_caps
188#define ibv_create_cq_attr_ex ibv_cq_init_attr_ex
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300189
Artemy Kovalyov7f03ef92018-12-12 10:01:51 +0200190#if HAVE_DECL_IBV_CREATE_CQ_ATTR_IGNORE_OVERRUN
191# define SET_IGNORE_OVERRUN(attr) \
192 (attr)->comp_mask = IBV_CQ_INIT_ATTR_MASK_FLAGS; \
193 (attr)->flags = IBV_CREATE_CQ_ATTR_IGNORE_OVERRUN;
194#else
195# define SET_IGNORE_OVERRUN(attr)
196#endif
197
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300198#define ibv_create_cq_ex_(ctx, attr, n, ch) ({ \
199 (attr)->cqe = n; \
200 (attr)->channel = ch; \
Artemy Kovalyovde0c6c12017-03-07 14:46:25 +0200201 (attr)->wc_flags = IBV_CREATE_CQ_SUP_WC_FLAGS; \
Artemy Kovalyov7f03ef92018-12-12 10:01:51 +0200202 SET_IGNORE_OVERRUN(attr) \
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300203 ibv_cq_ex_to_cq(ibv_create_cq_ex(ctx, attr)); })
204
Artemy Kovalyovb78f6de2016-08-30 17:41:21 +0300205#define ibv_query_device_(ctx, attr, attr2) ({ \
206 int ret = ibv_query_device_ex(ctx, NULL, attr); \
207 attr2 = &(attr)->orig_attr; ret ; })
208
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300209#define _wr_opcode opcode
210#define _wr_send_flags send_flags
Artemy Kovalyovfaf40a52017-07-15 12:30:50 +0300211#define _wc_opcode opcode
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200212//#define IBV_ODP_SUPPORT_IMPLICIT 2 pending kernel fix
213#define IBV_ODP_SUPPORT_IMPLICIT 0
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300214
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300215#endif
216
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200217#if HAVE_INFINIBAND_MLX5DV_H
218extern "C" {
219#include <infiniband/mlx5dv.h>
220}
221#endif
222
Artemy Kovalyov67cef552017-09-27 09:01:02 +0300223#ifdef __x86_64__
224
225#define PAGE 0x1000
226#define UP (1ULL<<47)
227
228#elif (__ppc64__|__PPC64__)
229
230#define PAGE 0x10000
231#define UP (1ULL<<46)
232
Artemy Kovalyov24239852018-11-08 10:56:15 +0200233#elif __aarch64__
234
235#define PAGE 0x1000
236#define UP (1ULL<<47)
237
238#else
239
240#error Unknown architecture
241
Artemy Kovalyov67cef552017-09-27 09:01:02 +0300242#endif
243
244#define PAGE_MASK (PAGE - 1)
245#define PAGE_ALIGN(x) ((x) & ~PAGE_MASK)
246#define PAGE_UPALIGN(x) (((x) + PAGE_MASK) & ~PAGE_MASK)
247
248
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300249#include "common.h"
250
251#define EXEC(x) do { \
252 VERBS_TRACE("%3d.%p: execute\t%s" #x "\n", __LINE__, this, this->env.lvl_str); \
253 this->env.lvl_str[this->env.lvl++] = ' '; \
254 ASSERT_NO_FATAL_FAILURE(this->x); \
255 this->env.lvl_str[--this->env.lvl] = 0; \
256 } while(0)
257
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300258#define INIT(x) do { \
259 if (!this->env.skip) { \
260 VERBS_TRACE("%3d.%p: initialize\t%s" #x "\n", __LINE__, this, this->env.lvl_str); \
261 this->env.lvl_str[this->env.lvl++] = ' '; \
262 EXPECT_NO_FATAL_FAILURE(this->x); \
263 this->env.lvl_str[--this->env.lvl] = 0; \
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200264 if (this->env.skip) { \
265 VERBS_TRACE("%3d.%p: failed\t%s" #x " - skipping test\n", __LINE__, this, this->env.lvl_str); \
266 return; \
267 } \
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300268 } \
269 } while(0)
270
Artemy Kovalyov062c3ef2016-08-29 11:14:47 +0300271#define EXECL(x) do { \
272 VERBS_TRACE("%3d.%p: execute\t%s" #x "\n", __LINE__, this, this->env.lvl_str); \
273 this->env.lvl_str[this->env.lvl++] = ' '; \
274 ASSERT_NO_FATAL_FAILURE(x); \
275 this->env.lvl_str[--this->env.lvl] = 0; \
276 } while(0)
277
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300278#define DO(x) do { \
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200279 VERBS_TRACE("%3d.%p: doing\t%s" #x "\n", __LINE__, this, this->env.lvl_str); \
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200280 if (this->env.run) \
281 ASSERT_EQ(0, x) << "errno: " << errno; \
282 else if (x) { \
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200283 VERBS_NOTICE("%3d.%p: failed\t%s" #x " - skipping test (errno %d)\n", __LINE__, this, this->env.lvl_str, errno); \
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200284 this->env.skip = 1; \
285 return; \
286 } \
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300287 } while(0)
288
289#define SET(x,y) do { \
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200290 VERBS_TRACE("%3d.%p: doing\t%s" #y "\n", __LINE__, this, this->env.lvl_str); \
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300291 x=y; \
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300292 if (this->env.run) \
293 ASSERT_TRUE(x) << #y << " errno: " << errno; \
294 else if (!x) { \
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200295 VERBS_NOTICE("%3d.%p: failed\t%s" #y " - skipping test (errno %d)\n", __LINE__, this, this->env.lvl_str, errno); \
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300296 this->env.skip = 1; \
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200297 return; \
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300298 } \
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300299 } while(0)
300
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200301#define SKIP(report) do { \
302 ::testing::UnitTest::GetInstance()->runtime_skip(report); \
303 return; \
Artemy Kovalyove69018f2016-11-17 16:17:29 +0200304 } while(0)
305
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200306
Artemy Kovalyov21e22a32016-06-20 17:14:47 +0300307#define CHK_SUT(FEATURE_NAME) \
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300308 do { \
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300309 if (this->skip) { \
Artemy Kovalyove69018f2016-11-17 16:17:29 +0200310 std::cout << "[ SKIPPED ] Feature " << #FEATURE_NAME << " lacks resources to be tested" << std::endl; \
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200311 SKIP(1); \
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300312 } \
313 this->run = 1; \
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300314 } while(0);
315
Artemy Kovalyove69018f2016-11-17 16:17:29 +0200316
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300317#define FREE(x,y) do { \
318 if (y) { \
319 VERBS_TRACE("%3d.%p: freeing\t%s" #x "\n", __LINE__, this, env.lvl_str); \
320 if (x(y)) { \
321 ADD_FAILURE() << "errno: " << errno; \
322 env.fatality = 1; \
323 } \
324 y = NULL; \
325 } \
326 } while(0)
327
Artemy Kovalyov0d953722017-07-15 12:36:17 +0300328#ifdef PALLADIUM
329#define POLL_RETRIES 8000000000ULL
330#else
331#define POLL_RETRIES 80000000ULL
332#endif
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300333
334#define ACTIVE (1 << 0)
335
336#define Q_KEY 0x11111111
337
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300338#define DC_KEY 1
339
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300340static void hexdump(const char *pfx, void *buff, size_t len) __attribute__ ((unused));
341static void hexdump(const char *pfx, void *buff, size_t len) {
342 unsigned char *p = (unsigned char*)buff, *end = (unsigned char*)buff + len, c;
343
344 while(p < end) {
345 printf("%4s %p: ", pfx, p /*- (unsigned char *)buff*/);
346 for (c=0; c<16; c++)
347 printf( p+c < end ? "%02x " : " ", p[c]);
348 for (c=0; c<16; c++)
349 printf( p+c < end ? "%c" : " ", p[c] >= 32 && p[c] < 128 ? p[c] : '.');
350 p += 16;
351 printf("\n");
352 }
353}
354
355struct ibvt_env {
356 ibvt_env &env;
357 char lvl_str[256];
358 int lvl;
359 int skip;
360 int fatality;
361 int flags;
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300362 int run;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300363
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200364 char meminfo[8192];
365 int ram_init;
366
Artemy Kovalyov79a00f72018-12-12 09:29:00 +0200367 struct ibv_send_wr *wr_list;
368 struct ibv_send_wr *wr_list_end;
369
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200370 void init_ram() {
371 int fd = open("/proc/meminfo", O_RDONLY);
372 ASSERT_GT(fd, 0);
Artemy Kovalyov441bd412018-02-24 20:55:49 +0200373 ASSERT_GT(read(fd, meminfo, sizeof(meminfo)), 0);
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200374 close(fd);
375 ram_init = 1;
376 }
377
378 void check_ram(const char* var, long val) {
379 if (!ram_init)
380 ASSERT_NO_FATAL_FAILURE(init_ram());
381 char *hit = strstr(meminfo, var);
Artemy Kovalyova5bfe6f2018-06-03 17:25:12 +0300382 ASSERT_TRUE(hit) << var;
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200383 if ((val >> 10) > atoi(hit + strlen(var))) {
384 VERBS_NOTICE("%smeminfo %s is lower than %ld - skipping test\n",
385 lvl_str, var, val >> 10);
386 skip = 1;
387 }
388 }
389
Artemy Kovalyov79a00f72018-12-12 09:29:00 +0200390 virtual void add_wr(ibv_send_wr *wr) {
391 if (wr_list)
392 wr_list_end->next = wr;
393 else
394 wr_list = wr;
395 wr_list_end = wr;
396 }
397
398 virtual void free_wr() {
399 while (wr_list) {
400 struct ibv_send_wr *wr = wr_list;
401 wr_list = wr_list->next;
402 free(wr);
403 }
404 }
405
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300406 ibvt_env() :
407 env(*this),
408 lvl(0),
409 skip(0),
410 fatality(0),
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300411 flags(ACTIVE),
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200412 run(0),
Artemy Kovalyov79a00f72018-12-12 09:29:00 +0200413 ram_init(0),
414 wr_list(NULL)
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300415 {
416 memset(lvl_str, 0, sizeof(lvl_str));
417 }
418};
419
420struct ibvt_obj {
421 ibvt_env &env;
422
423 ibvt_obj(ibvt_env &e) : env(e) { }
424
425 virtual void init() = 0;
426};
427
428struct ibvt_ctx : public ibvt_obj {
429 struct ibv_context *ctx;
430 ibvt_ctx *other;
431 struct ibv_device *dev;
Artemy Kovalyovb78f6de2016-08-30 17:41:21 +0300432 struct ibv_device_attr *dev_attr_orig;
Artemy Kovalyov21e22a32016-06-20 17:14:47 +0300433 struct ibv_device_attr_ex dev_attr;
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200434 struct ibv_port_attr port_attr;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300435 uint8_t port_num;
436 uint16_t lid;
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200437 union ibv_gid gid;
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300438 char *pdev_name;
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300439 char *vdev_name;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300440
Artemy Kovalyov441bd412018-02-24 20:55:49 +0200441#if HAVE_INFINIBAND_VERBS_EXP_H
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300442
443#define DEV_FS "/sys/class/infiniband_verbs"
444#define DEBUGFS "/sys/kernel/debug/mlx5"
445
446 void init_sysfs() {
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300447 char path[PATH_MAX];
448 char pdev[PATH_MAX], *p = pdev, *tok;
449 struct stat st;
450
451 sprintf(path, "/sys/class/infiniband/%s", ibv_get_device_name(dev));
Artemy Kovalyov441bd412018-02-24 20:55:49 +0200452 if (readlink(path, pdev, PATH_MAX) <= 0)
453 return;
454
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300455 while ((tok = strsep(&p, "/"))) {
456 if (tok[0] == '.')
457 continue;
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300458 sprintf(path, DEBUGFS "/%s", tok);
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300459 if (stat(path, &st) == 0) {
460 pdev_name = strdup(tok);
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300461 break;
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300462 }
463 }
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300464
465 DIR *verbs = opendir(DEV_FS);
466 struct dirent *d;
467 char buff[PATH_MAX];
468 int fd, len;
469
470 while ((d = readdir(verbs))) {
471 sprintf(path, DEV_FS "/%s/ibdev",
472 d->d_name);
473 fd = open(path, O_RDONLY);
474 if (fd < 0)
475 continue;
476 len = read(fd, buff, sizeof(buff));
477 close(fd);
478 buff[len-1] = 0;
479 if (!strcmp(buff, ibv_get_device_name(dev))) {
480 vdev_name = strdup(d->d_name);
481 break;
482 }
483 }
484 closedir(verbs);
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300485 }
486
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300487 int read_sysfs(const char* dir, char* dev_name, const char* var) {
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300488 char path[PATH_MAX];
489 char buff[PATH_MAX];
490 int fd;
491
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300492 sprintf(path, "%s/%s/%s", dir, dev_name, var);
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300493 fd = open(path, O_RDONLY);
494
495 if (fd < 0)
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300496 return -1;
Artemy Kovalyov441bd412018-02-24 20:55:49 +0200497 if (read(fd, buff, sizeof(buff)) <= 0) {
498 close(fd);
499 return -1;
500 }
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300501 close(fd);
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300502 return atoi(buff);
Artemy Kovalyov207d0742016-09-13 12:54:47 +0300503 }
504
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300505 void check_debugfs(const char* var, int val) {
506 if (!pdev_name)
507 return;
508 int val_fs = read_sysfs(DEBUGFS, pdev_name, var);
509 VERBS_INFO("%3d.%p: debugfs\t%s %s = %d\n", __LINE__,
510 this, env.lvl_str, var, val_fs);
511 ASSERT_GE(val_fs, val) << var;
512 }
513
514 void read_dev_fs(const char* var, int* val) {
515 if (!vdev_name)
516 return;
517 *val = read_sysfs(DEV_FS, vdev_name, var);
518 VERBS_INFO("%3d.%p: dev fs\t%s %s = %d\n", __LINE__,
519 this, env.lvl_str, var, *val);
520 }
521
522 void check_dev_fs(const char* var, int val) {
523 if (!vdev_name)
524 return;
525 int val_fs = read_sysfs(DEV_FS, vdev_name, var);
526 VERBS_INFO("%3d.%p: dev fs\t%s %s = %d\n", __LINE__,
527 this, env.lvl_str, var, val_fs);
528 ASSERT_GE(val_fs, val) << var;
529 }
530#else
531 void init_sysfs() {}
532 void check_debugfs(const char* var, int val) {}
533 void read_dev_fs(const char* var, int* val) {}
534 void check_dev_fs(const char* var, int val) {}
535#endif
536
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200537 ibvt_ctx(ibvt_env &e, ibvt_ctx *o = NULL) :
538 ibvt_obj(e),
539 ctx(NULL),
540 other(o),
541 port_num(0),
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300542 pdev_name(NULL),
543 vdev_name(NULL) {}
Artemy-Mellanox409fabc2017-02-19 00:32:51 +0200544
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200545 virtual bool check_port(struct ibv_device *dev) {
Artemy Kovalyov218e2c62017-02-13 13:40:06 +0200546 if (getenv("IBV_DEV") && strcmp(ibv_get_device_name(dev), getenv("IBV_DEV")))
Artemy Kovalyova36c8fe2017-01-23 21:45:45 +0200547 return false;
548 if (port_attr.state == IBV_PORT_ACTIVE)
549 return true;
Moses Reuben06b0ac52016-12-15 11:15:09 -0500550 return false;
551 }
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300552
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200553
554 int grh_required() {
555 return port_attr.link_layer == IBV_LINK_LAYER_ETHERNET;
556 }
557
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200558 virtual ibv_context *open_device(struct ibv_device *ibdev) {
559 return ibv_open_device(ibdev);
560 }
561
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300562 virtual void init() {
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300563 struct ibv_device **dev_list = NULL;
564 int num_devices;
565 if (ctx)
566 return;
567
568 dev_list = ibv_get_device_list(&num_devices);
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200569 for (int devn = 0; devn < num_devices; devn++) {
570 if (other && other->dev == dev_list[devn])
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300571 continue;
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200572 SET(ctx, open_device(dev_list[devn]));
Artemy Kovalyovb78f6de2016-08-30 17:41:21 +0300573 memset(&dev_attr, 0, sizeof(dev_attr));
574 DO(ibv_query_device_(ctx, &dev_attr, dev_attr_orig));
575 for (int port = 1; port <= dev_attr_orig->phys_port_cnt; port++) {
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300576 DO(ibv_query_port(ctx, port, &port_attr));
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200577 if (!check_port(dev_list[devn]))
Moses Reuben06b0ac52016-12-15 11:15:09 -0500578 continue;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300579
580 port_num = port;
581 lid = port_attr.lid;
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200582 DO(ibv_query_gid(ctx, port_num, 0, &gid));
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300583 break;
584 }
585 if (port_num) {
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200586 dev = dev_list[devn];
587 VERBS_INFO("dev %s\n", ibv_get_device_name(dev));
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300588 break;
589 } else {
590 DO(ibv_close_device(ctx));
Artemy Kovalyov5070fdf2016-09-07 16:31:34 +0300591 ctx = NULL;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300592 }
593 }
Artemy Kovalyov19ecad32018-12-05 20:49:49 +0200594 if (dev_list)
595 ibv_free_device_list(dev_list);
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200596 if (!port_num) {
597 VERBS_NOTICE("suitable port not found\n");
Artemy Kovalyovb78f6de2016-08-30 17:41:21 +0300598 env.skip = 1;
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200599 }
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300600 }
601
602 virtual ~ibvt_ctx() {
603 FREE(ibv_close_device, ctx);
604 }
605};
606
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200607#if HAVE_DECL_MLX5DV_CONTEXT_FLAGS_DEVX
608struct ibvt_ctx_devx : public ibvt_ctx {
609 ibvt_ctx_devx(ibvt_env &e, ibvt_ctx *o = NULL) :
610 ibvt_ctx(e, o) {}
611
612 virtual ibv_context *open_device(struct ibv_device *ibdev) {
613 struct ibv_context *res;
614 struct mlx5dv_context_attr dv_attr = {};
615
616 dv_attr.flags |= MLX5DV_CONTEXT_FLAGS_DEVX;
617 res = mlx5dv_open_device(ibdev, &dv_attr);
618
619 return res;
620 }
621};
622#endif
623
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300624struct ibvt_pd : public ibvt_obj {
625 struct ibv_pd *pd;
626 ibvt_ctx &ctx;
627
628 ibvt_pd(ibvt_env &e, ibvt_ctx &c) : ibvt_obj(e), pd(NULL), ctx(c) {}
629
630 virtual void init() {
631 if (pd)
632 return;
633 EXEC(ctx.init());
634 SET(pd, ibv_alloc_pd(ctx.ctx));
635 }
636
637 virtual ~ibvt_pd() {
638 FREE(ibv_dealloc_pd, pd);
639 }
640};
641
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300642struct ibvt_cq;
643
644struct ibvt_wc {
645 struct ibv_wc wc;
646 ibvt_cq &cq;
647
648 struct ibv_wc operator()() {
649 return wc;
650 }
651
652 ibvt_wc(ibvt_cq &c) : cq(c) {
653 memset(&wc, 0, sizeof(wc));
654 }
655
656 virtual ~ibvt_wc() ;
657};
658
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300659struct ibvt_cq : public ibvt_obj {
660 struct ibv_cq *cq;
661 ibvt_ctx &ctx;
662
663 ibvt_cq(ibvt_env &e, ibvt_ctx &c) : ibvt_obj(e), cq(NULL), ctx(c) {}
664
665 virtual void init_attr(struct ibv_create_cq_attr_ex &attr, int &cqe) {
666 memset(&attr, 0, sizeof(attr));
Artemy Kovalyov8b8ef172017-02-13 13:46:22 +0000667 cqe = 0x1000;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300668 }
669
670 virtual void init() {
671 struct ibv_create_cq_attr_ex attr;
672 int cqe;
673 if (cq)
674 return;
675 EXEC(ctx.init());
676 init_attr(attr, cqe);
677 SET(cq, ibv_create_cq_ex_(ctx.ctx, &attr, cqe, NULL));
678 }
679
680 virtual ~ibvt_cq() {
681 FREE(ibv_destroy_cq, cq);
682 }
683
684 virtual void arm() {}
685
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300686 virtual void poll() {
687 ibvt_wc wc(*this);
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300688
689 VERBS_TRACE("%d.%p polling...\n", __LINE__, this);
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300690 EXEC(do_poll(wc));
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300691
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300692 VERBS_TRACE("poll status %s(%d) opcode %d len %d qp %x lid %x flags %lx\n",
693 ibv_wc_status_str(wc().status),
694 wc().status, wc()._wc_opcode,
695 wc().byte_len, wc().qp_num,
696 wc().slid, (uint64_t)wc().wc_flags);
697 //if (wc().status) getchar();
698 ASSERT_FALSE(wc().status) << ibv_wc_status_str(wc().status);
699 }
700
Artemy Kovalyov441bd412018-02-24 20:55:49 +0200701#if HAVE_INFINIBAND_VERBS_EXP_H
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300702 virtual void do_poll(struct ibvt_wc &wc) {
703 long result = 0, retries = POLL_RETRIES;
Artemy Kovalyov8d830982017-03-09 12:22:04 +0200704 errno = 0;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300705 while (!result && --retries) {
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300706 result = ibv_poll_cq(cq, 1, &wc.wc);
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300707 ASSERT_GE(result,0);
708 }
709 ASSERT_GT(retries,0) << "errno: " << errno;
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300710 }
711#else
712 struct ibv_cq_ex *cq2() {
713 return (struct ibv_cq_ex *)this->cq;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300714 }
Artemy Kovalyovfaf40a52017-07-15 12:30:50 +0300715
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300716 virtual void do_poll(struct ibvt_wc &wc) {
717 long result = 0, retries = POLL_RETRIES;
718 struct ibv_poll_cq_attr attr = {};
719
720 errno = 0;
721 while (--retries) {
722 result = ibv_start_poll(cq2(), &attr);
723 if (!result)
724 break;
725 ASSERT_EQ(ENOENT, result);
726 }
727 ASSERT_GT(retries,0) << "errno: " << errno;
728
729 wc.wc.status = cq2()->status;
730 wc.wc.wr_id = cq2()->wr_id;
731 wc.wc.opcode = ibv_wc_read_opcode(cq2());
732 wc.wc.wc_flags = ibv_wc_read_wc_flags(cq2());
733 wc.wc.byte_len = ibv_wc_read_byte_len(cq2());
734 wc.wc.slid = ibv_wc_read_slid(cq2());
735 wc.wc.qp_num = ibv_wc_read_qp_num(cq2());
736
737 }
738#endif
Moses Reuben06b0ac52016-12-15 11:15:09 -0500739 virtual void poll_arrive(int n) {
740 struct ibv_wc wc[n];
Artemy Kovalyov0d953722017-07-15 12:36:17 +0300741 long result = 0, retries = POLL_RETRIES;
Moses Reuben06b0ac52016-12-15 11:15:09 -0500742
743 VERBS_TRACE("%d.%p polling...\n", __LINE__, this);
744
745 while (!result && --retries) {
746 result = ibv_poll_cq(cq, n, wc);
747 ASSERT_GE(result,0);
748 }
749 ASSERT_EQ(result,0) << "errno: " << errno;
750
751 }
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300752};
753
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300754inline ibvt_wc::~ibvt_wc() {
Artemy Kovalyov441bd412018-02-24 20:55:49 +0200755#if !HAVE_INFINIBAND_VERBS_EXP_H
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300756 ibv_end_poll(cq.cq2());
757#endif
758}
759
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300760struct ibvt_cq_event : public ibvt_cq {
761 struct ibv_comp_channel *channel;
762 int num_cq_events;
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300763 int solicited_only;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300764
Artemy Kovalyovb78f6de2016-08-30 17:41:21 +0300765 ibvt_cq_event(ibvt_env &e, ibvt_ctx &c) :
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300766 ibvt_cq(e, c),
767 channel(NULL),
768 num_cq_events(0),
769 solicited_only(0) {}
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300770
771 virtual void init() {
772 struct ibv_create_cq_attr_ex attr;
773 int cqe;
774 if (cq)
775 return;
776 EXEC(ctx.init());
777 SET(channel, ibv_create_comp_channel(ctx.ctx));
778 init_attr(attr, cqe);
779 SET(cq, ibv_create_cq_ex_(ctx.ctx, &attr, cqe, channel));
780 }
781
782 virtual ~ibvt_cq_event() {
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300783 if (num_cq_events)
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300784 ibv_ack_cq_events(cq, num_cq_events);
785 FREE(ibv_destroy_cq, cq);
786 FREE(ibv_destroy_comp_channel, channel);
787 }
788
789 virtual void arm() {
790 num_cq_events = 0;
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300791 DO(ibv_req_notify_cq(cq, solicited_only));
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300792 }
793
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300794 virtual void do_poll(struct ibvt_wc &wc) {
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300795 struct ibv_cq *ev_cq;
796 void *ev_ctx;
797
798 DO(ibv_get_cq_event(channel, &ev_cq, &ev_ctx));
799 ASSERT_EQ(ev_cq, cq);
800 num_cq_events++;
Artemy Kovalyov3acead42017-09-27 09:07:49 +0300801 DO(ibv_req_notify_cq(cq, solicited_only));
802 EXEC(ibvt_cq::do_poll(wc));
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300803 }
804};
805
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200806struct ibvt_abstract_mr : public ibvt_obj {
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300807 size_t size;
Artemy Kovalyove69018f2016-11-17 16:17:29 +0200808 intptr_t addr;
Artemy Kovalyov21e22a32016-06-20 17:14:47 +0300809 char *buff;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300810
Artemy Kovalyov67cef552017-09-27 09:01:02 +0300811 char *mem;
812 size_t mem_size;
813
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200814 ibvt_abstract_mr(ibvt_env &e, size_t s, intptr_t a) :
Artemy Kovalyov21e22a32016-06-20 17:14:47 +0300815 ibvt_obj(e),
Artemy Kovalyov21e22a32016-06-20 17:14:47 +0300816 size(s),
Artemy Kovalyove69018f2016-11-17 16:17:29 +0200817 addr(a),
Artemy Kovalyovb58b1c02017-10-30 14:33:00 +0200818 buff(NULL),
819 mem(NULL) {}
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300820
Artemy Kovalyova36c8fe2017-01-23 21:45:45 +0200821 virtual int mmap_flags() {
822 return MAP_PRIVATE|MAP_ANON;
823 }
824
Artemy Kovalyov67cef552017-09-27 09:01:02 +0300825 virtual void init_mmap() {
Artemy Kovalyova36c8fe2017-01-23 21:45:45 +0200826 int flags = mmap_flags();
Artemy Kovalyov67cef552017-09-27 09:01:02 +0300827 if (addr) {
828 flags |= MAP_FIXED;
829 mem_size = PAGE_UPALIGN(size + (addr & PAGE_MASK));
830 } else {
831 mem_size = size;
832 }
833
834 mem = (char*)mmap((void*)PAGE_ALIGN(addr),
835 mem_size, PROT_READ|PROT_WRITE,
836 flags, -1, 0);
837 ASSERT_NE(mem, MAP_FAILED);
838
839 buff = addr ? (char*)addr : mem;
840 }
841
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200842 virtual ~ibvt_abstract_mr() {
Artemy Kovalyovb58b1c02017-10-30 14:33:00 +0200843 if (mem && mem != MAP_FAILED)
844 munmap(mem, mem_size);
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300845 }
846
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200847 virtual uint32_t lkey() = 0;
848
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300849 virtual void fill() {
850 EXEC(init());
851 for (size_t i = 0; i < size; i++)
852 buff[i] = i & 0xff;
853 }
854
Artemy Kovalyov0fdd2ef2018-07-16 15:50:14 +0000855 virtual void check(size_t skip = 0, size_t shift = 0, int repeat = 1, size_t length = 0) {
Artemy Kovalyov179ad632018-04-28 20:12:16 +0000856 if (!length)
857 length = size;
Artemy Kovalyove5c93662017-01-30 17:17:22 +0200858 for (int n = 0; n < repeat; n++)
Artemy Kovalyov179ad632018-04-28 20:12:16 +0000859 for (size_t i = skip + n * (length / repeat); i < length / repeat - shift; i++)
Artemy Kovalyove5c93662017-01-30 17:17:22 +0200860 ASSERT_EQ((char)((i + shift) & 0xff), buff[i]) << "i=" << i;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300861 memset(buff, 0, size);
862 }
863
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300864 virtual void dump(size_t offset = 0,
865 size_t length = 0,
866 const char *pfx = "") {
867 hexdump(pfx, buff + offset, length ?: size);
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300868 }
869
Artemy Kovalyovfc636ed2016-11-27 13:16:39 +0200870 virtual struct ibv_sge sge(intptr_t start, size_t length) {
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300871 struct ibv_sge ret;
872
873 memset(&ret, 0, sizeof(ret));
Artemy Kovalyovfc636ed2016-11-27 13:16:39 +0200874 ret.addr = (intptr_t)buff + start;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300875 ret.length = length;
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200876 ret.lkey = lkey();
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300877
878 return ret;
879 }
Artemy Kovalyov21e22a32016-06-20 17:14:47 +0300880
881 virtual struct ibv_sge sge() { return sge(0, size); }
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300882};
883
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200884struct ibvt_mr : public ibvt_abstract_mr {
885 ibvt_pd &pd;
886 long access_flags;
887 struct ibv_mr *mr;
888
889 ibvt_mr(ibvt_env &e, ibvt_pd &p, size_t s, intptr_t a = 0,
890 long af = IBV_ACCESS_LOCAL_WRITE |
891 IBV_ACCESS_REMOTE_READ |
892 IBV_ACCESS_REMOTE_WRITE) :
893 ibvt_abstract_mr(e, s, a), pd(p), access_flags(af), mr(NULL) {}
894
895 virtual void init() {
896 if (mr)
897 return;
898 EXEC(pd.init());
899 EXEC(init_mmap());
900 SET(mr, ibv_reg_mr(pd.pd, buff, size, access_flags));
901 VERBS_TRACE("\t\t\t\tibv_reg_mr(pd, %p, %zx, %lx) = %x\n", buff, size, access_flags, mr->lkey);
902 }
903
904 virtual uint32_t lkey() {
905 return mr->lkey;
906 }
907
908 virtual ~ibvt_mr() {
909 FREE(ibv_dereg_mr, mr);
910 }
911};
912
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300913struct ibvt_srq : public ibvt_obj {
914 struct ibv_srq *srq;
915
916 ibvt_pd &pd;
917 ibvt_cq &cq;
918
919 ibvt_srq(ibvt_env &e, ibvt_pd &p, ibvt_cq &c) :
920 ibvt_obj(e), srq(NULL), pd(p), cq(c) {}
921
922 ~ibvt_srq() {
923 FREE(ibv_destroy_srq, srq);
924 }
925
926 virtual void init_attr(struct ibv_srq_init_attr_ex &attr) {
Artemy Kovalyov441bd412018-02-24 20:55:49 +0200927#if HAVE_INFINIBAND_VERBS_EXP_H
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300928 attr.comp_mask =
929 IBV_EXP_CREATE_SRQ_CQ;
930 attr.srq_type = IBV_EXP_SRQT_BASIC;
931 attr.pd = pd.pd;
932 attr.cq = cq.cq;
933 attr.base.attr.max_wr = 128;
934 attr.base.attr.max_sge = 1;
Artemy Kovalyov441bd412018-02-24 20:55:49 +0200935#else
936 attr.comp_mask =
937 IBV_SRQ_INIT_ATTR_TYPE |
938 IBV_SRQ_INIT_ATTR_PD |
939 IBV_SRQ_INIT_ATTR_CQ;
940 attr.pd = pd.pd;
941 attr.cq = cq.cq;
942 attr.attr.max_wr = 128;
943 attr.attr.max_sge = 1;
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300944#endif
945 }
946
947 virtual void init() {
948 struct ibv_srq_init_attr_ex attr = {};
949 if (srq)
950 return;
951
Artemy Kovalyovc0206e62017-09-13 13:34:04 +0300952 INIT(pd.init());
953 INIT(cq.init());
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300954 init_attr(attr);
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300955 SET(srq, ibv_create_srq_ex(pd.ctx.ctx, &attr));
956 }
957
958 virtual void recv(ibv_sge sge) {
959 struct ibv_recv_wr wr;
960 struct ibv_recv_wr *bad_wr = NULL;
961
962 memset(&wr, 0, sizeof(wr));
963 wr.next = NULL;
964 wr.wr_id = 0x56789;
965 wr.sg_list = &sge;
966 wr.num_sge = 1;
967 DO(ibv_post_srq_recv(srq, &wr, &bad_wr));
968 }
969};
970
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300971struct ibvt_qp : public ibvt_obj {
972 struct ibv_qp *qp;
973 ibvt_pd &pd;
974 ibvt_cq &cq;
975
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +0200976 ibvt_qp(ibvt_env &e, ibvt_pd &p, ibvt_cq &c) : ibvt_obj(e), qp(NULL), pd(p), cq(c) {}
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300977
978 virtual ~ibvt_qp() {
979 FREE(ibv_destroy_qp, qp);
980 }
981
982 virtual void init_attr(struct ibv_qp_init_attr_ex &attr) {
983 memset(&attr, 0, sizeof(attr));
Artemy Kovalyov8b8ef172017-02-13 13:46:22 +0000984 attr.cap.max_send_wr = 0x1000;
985 attr.cap.max_recv_wr = 0x1000;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +0300986 attr.cap.max_send_sge = 1;
987 attr.cap.max_recv_sge = 1;
988 attr.send_cq = cq.cq;
989 attr.recv_cq = cq.cq;
990 attr.pd = pd.pd;
991 attr.comp_mask = IBV_QP_INIT_ATTR_PD;
992 }
993
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +0300994 virtual void init() {
995 struct ibv_qp_init_attr_ex attr;
996 INIT(pd.init());
997 INIT(cq.init());
998 init_attr(attr);
999 SET(qp, ibv_create_qp_ex(pd.ctx.ctx, &attr));
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +02001000 INIT(init_dv());
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001001 }
1002
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +02001003#if HAVE_DECL_MLX5DV_INIT_OBJ
1004 uint8_t *sq;
1005 volatile uint32_t *qp_dbr;
1006 void *uar_ptr;
1007 int sqi;
1008 int sq_len;
1009
1010 virtual void init_dv() {
1011 struct mlx5dv_qp dvqp = {};
1012 struct mlx5dv_obj dv = {};
1013
1014 dv.qp.in = qp;
1015 dv.qp.out = &dvqp;
1016 DO(mlx5dv_init_obj(&dv, MLX5DV_OBJ_QP));
1017 sq = (uint8_t *)dvqp.sq.buf;
1018 qp_dbr = dvqp.dbrec;
1019 uar_ptr = dvqp.bf.reg;
1020 sq_len = dvqp.sq.stride * dvqp.sq.wqe_cnt;
1021 sqi = 0;
1022 }
1023
1024 void *get_wqe(int i) {
1025 void *wqe = sq + ((sqi + i) * MLX5_SEND_WQE_BB) % sq_len;
1026 memset(wqe, 0, MLX5_SEND_WQE_BB);
1027 return wqe;
1028 }
1029
1030 void ring_db(int i) {
1031 void *ctrl = sq + (sqi * MLX5_SEND_WQE_BB) % sq_len;
1032
1033 //hexdump("WQE", ctrl, i * MLX5_SEND_WQE_BB);
1034
1035 sqi += i;
1036 asm volatile("" ::: "memory");
1037
1038 qp_dbr[MLX5_SND_DBR] = htobe32(sqi & 0xffff);
1039 asm volatile("" ::: "memory");
1040
1041 *(uint64_t *)uar_ptr = *(uint64_t *)ctrl;
1042 asm volatile("" ::: "memory");
1043 }
1044#else
1045 virtual void init_dv() {}
1046#endif
1047
Artemy Kovalyov79a00f72018-12-12 09:29:00 +02001048 virtual void post_all_wr() {
1049 struct ibv_send_wr *bad_wr = NULL;
1050 DO(ibv_post_send(qp, env.wr_list, &bad_wr));
1051 env.free_wr();
1052 }
1053
Artemy Kovalyovfc636ed2016-11-27 13:16:39 +02001054 virtual void recv(ibv_sge sge) {
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001055 struct ibv_recv_wr wr;
1056 struct ibv_recv_wr *bad_wr = NULL;
1057
1058 memset(&wr, 0, sizeof(wr));
1059 wr.next = NULL;
1060 wr.wr_id = 0;
1061 wr.sg_list = &sge;
1062 wr.num_sge = 1;
1063 DO(ibv_post_recv(qp, &wr, &bad_wr));
1064 }
1065
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001066 virtual void post_send(ibv_sge sge, enum ibv_wr_opcode opcode,
1067 int flags = IBV_SEND_SIGNALED) {
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001068 struct ibv_send_wr wr;
1069 struct ibv_send_wr *bad_wr = NULL;
1070
1071 memset(&wr, 0, sizeof(wr));
1072 wr.next = NULL;
1073 wr.wr_id = 0;
1074 wr.sg_list = &sge;
1075 wr.num_sge = 1;
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001076 wr._wr_opcode = opcode;
1077 wr._wr_send_flags = flags;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001078 DO(ibv_post_send(qp, &wr, &bad_wr));
1079 }
1080
Artemy Kovalyov79a00f72018-12-12 09:29:00 +02001081 virtual void rdma_wr(ibv_sge src_sge, ibv_sge dst_sge, enum ibv_wr_opcode opcode, int flags = IBV_SEND_SIGNALED) {
1082 struct __rdma_wr {
1083 ibv_send_wr wr;
1084 ibv_sge sge;
1085 } *wr = (__rdma_wr *)calloc(1, sizeof(*wr));
Artemy Kovalyov21e22a32016-06-20 17:14:47 +03001086
Artemy Kovalyov79a00f72018-12-12 09:29:00 +02001087 wr->sge = src_sge;
1088 wr->wr.wr_id = 0;
1089 wr->wr.sg_list = &wr->sge;
1090 wr->wr.num_sge = 1;
1091 wr->wr._wr_opcode = opcode;
1092 wr->wr._wr_send_flags = flags;
Artemy Kovalyov21e22a32016-06-20 17:14:47 +03001093
Artemy Kovalyov79a00f72018-12-12 09:29:00 +02001094 wr->wr.wr.rdma.remote_addr = dst_sge.addr;
1095 wr->wr.wr.rdma.rkey = dst_sge.lkey;
Artemy Kovalyov21e22a32016-06-20 17:14:47 +03001096
Artemy Kovalyov79a00f72018-12-12 09:29:00 +02001097 env.add_wr(&wr->wr);
1098 }
1099
1100 virtual void rdma(ibv_sge src_sge, ibv_sge dst_sge, enum ibv_wr_opcode opcode, int flags = IBV_SEND_SIGNALED) {
1101 rdma_wr(src_sge, dst_sge, opcode, flags);
1102 EXEC(post_all_wr());
Artemy Kovalyov21e22a32016-06-20 17:14:47 +03001103 }
1104
Artemy Kovalyov921fbbe2017-08-20 02:51:49 +03001105 virtual void rdma2(ibv_sge src_sge1,
1106 ibv_sge src_sge2,
1107 ibv_sge dst_sge,
1108 enum ibv_wr_opcode opcode,
1109 enum ibv_send_flags flags = IBV_SEND_SIGNALED) {
1110 struct ibv_send_wr wr;
1111 struct ibv_send_wr *bad_wr = NULL;
1112 struct ibv_sge sg[2];
1113
1114
1115 sg[0] = src_sge1;
1116 sg[1] = src_sge2;
1117 memset(&wr, 0, sizeof(wr));
1118 wr.next = NULL;
1119 wr.wr_id = 0;
1120 wr.sg_list = sg;
1121 wr.num_sge = 2;
1122 wr._wr_opcode = opcode;
1123 wr._wr_send_flags = flags;
1124
1125 wr.wr.rdma.remote_addr = dst_sge.addr;
1126 wr.wr.rdma.rkey = dst_sge.lkey;
1127
1128 DO(ibv_post_send(qp, &wr, &bad_wr));
1129 }
1130
Artemy Kovalyovfc636ed2016-11-27 13:16:39 +02001131 virtual void send(ibv_sge sge) {
1132 post_send(sge, IBV_WR_SEND);
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001133 }
Artemy Kovalyova4bd4252017-07-15 12:34:20 +03001134
1135 virtual void connect(ibvt_qp *remote) = 0;
Artemy Kovalyovbe5fe9b2018-02-24 20:51:48 +02001136
1137 virtual int hdr_len() { return 0; }
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001138};
1139
1140struct ibvt_qp_rc : public ibvt_qp {
1141 ibvt_qp *remote;
1142
1143 ibvt_qp_rc(ibvt_env &e, ibvt_pd &p, ibvt_cq &c) : ibvt_qp(e, p, c) {}
1144
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001145 virtual void init_attr(struct ibv_qp_init_attr_ex &attr) {
1146 ibvt_qp::init_attr(attr);
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001147 attr.qp_type = IBV_QPT_RC;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001148 }
1149
1150 virtual void connect(ibvt_qp *remote) {
1151 struct ibv_qp_attr attr;
1152 int flags;
1153
1154 this->remote = remote;
1155
1156 memset(&attr, 0, sizeof(attr));
1157 attr.qp_state = IBV_QPS_INIT;
1158 attr.port_num = pd.ctx.port_num;
1159 attr.pkey_index = 0;
1160 attr.qp_access_flags = IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_READ | IBV_ACCESS_REMOTE_WRITE;
1161 flags = IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT | IBV_QP_ACCESS_FLAGS;
1162 DO(ibv_modify_qp(qp, &attr, flags));
1163
1164 memset(&attr, 0, sizeof(attr));
1165 attr.qp_state = IBV_QPS_RTR;
1166 attr.path_mtu = IBV_MTU_512;
1167 attr.dest_qp_num = remote->qp->qp_num;
1168 attr.rq_psn = 0;
1169 attr.max_dest_rd_atomic = 1;
1170 attr.min_rnr_timer = 12;
Artemy Kovalyov19ecad32018-12-05 20:49:49 +02001171 if (!pd.ctx.grh_required()) {
1172 attr.ah_attr.is_global = 0;
1173 } else {
1174 attr.ah_attr.is_global = 1;
1175 attr.ah_attr.grh.hop_limit = 1;
1176 attr.ah_attr.grh.dgid = remote->pd.ctx.gid;
1177 attr.ah_attr.grh.sgid_index = 0;
1178 }
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001179 attr.ah_attr.dlid = remote->pd.ctx.lid;
1180 attr.ah_attr.sl = 0;
1181 attr.ah_attr.src_path_bits = 0;
1182 attr.ah_attr.port_num = remote->pd.ctx.port_num;
1183 flags = IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU | IBV_QP_DEST_QPN |
1184 IBV_QP_RQ_PSN | IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER;
1185 DO(ibv_modify_qp(qp, &attr, flags));
1186
1187 memset(&attr, 0, sizeof(attr));
1188 attr.qp_state = IBV_QPS_RTS;
1189 attr.timeout = 14;
1190 attr.retry_cnt = 7;
1191 attr.rnr_retry = 7;
1192 attr.sq_psn = 0;
1193 attr.max_rd_atomic = 1;
1194 flags = IBV_QP_STATE | IBV_QP_TIMEOUT | IBV_QP_RETRY_CNT |
1195 IBV_QP_RNR_RETRY | IBV_QP_SQ_PSN | IBV_QP_MAX_QP_RD_ATOMIC;
1196
1197 DO(ibv_modify_qp(qp, &attr, flags));
1198 }
1199};
1200
1201struct ibvt_qp_ud : public ibvt_qp_rc {
1202 struct ibv_ah *ah;
1203
1204 ibvt_qp_ud(ibvt_env &e, ibvt_pd &p, ibvt_cq &c) : ibvt_qp_rc(e, p, c) {}
1205
Artemy Kovalyov19ecad32018-12-05 20:49:49 +02001206 virtual ~ibvt_qp_ud() {
1207 FREE(ibv_destroy_ah, ah);
1208 }
1209
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001210 virtual void init_attr(struct ibv_qp_init_attr_ex &attr) {
1211 ibvt_qp::init_attr(attr);
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001212 attr.qp_type = IBV_QPT_UD;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001213 }
1214
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001215 virtual void post_send(ibv_sge sge, enum ibv_wr_opcode opcode,
1216 int flags = IBV_SEND_SIGNALED) {
Artemy Kovalyov7ad124b2016-11-28 12:08:28 +02001217 struct ibv_sge sge_ud = sge;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001218 struct ibv_send_wr wr;
1219 struct ibv_send_wr *bad_wr = NULL;
1220
Artemy Kovalyov7ad124b2016-11-28 12:08:28 +02001221 sge_ud.addr += 40;
1222 sge_ud.length -= 40;
1223
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001224 memset(&wr, 0, sizeof(wr));
1225 wr.next = NULL;
1226 wr.wr_id = 0;
Artemy Kovalyov7ad124b2016-11-28 12:08:28 +02001227 wr.sg_list = &sge_ud;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001228 wr.num_sge = 1;
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001229 wr._wr_opcode = opcode;
1230 wr._wr_send_flags = flags;
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001231
1232 wr.wr.ud.ah = ah;
1233 wr.wr.ud.remote_qpn = remote->qp->qp_num;
1234 wr.wr.ud.remote_qkey = Q_KEY;
1235
1236 DO(ibv_post_send(qp, &wr, &bad_wr));
1237 }
1238
1239 virtual void connect(ibvt_qp *remote) {
1240 struct ibv_qp_attr attr;
1241 int flags;
1242
1243 this->remote = remote;
1244
1245 memset(&attr, 0, sizeof(attr));
1246 attr.qp_state = IBV_QPS_INIT;
1247 attr.port_num = pd.ctx.port_num;
1248 attr.pkey_index = 0;
1249 attr.qkey = Q_KEY;
1250 flags = IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT | IBV_QP_QKEY;
1251 DO(ibv_modify_qp(qp, &attr, flags));
1252
1253 memset(&attr, 0, sizeof(attr));
1254 attr.qp_state = IBV_QPS_RTR;
1255 flags = IBV_QP_STATE;
1256 DO(ibv_modify_qp(qp, &attr, flags));
1257
Artemy Kovalyov19ecad32018-12-05 20:49:49 +02001258 if (!pd.ctx.grh_required()) {
1259 attr.ah_attr.is_global = 0;
1260 } else {
1261 attr.ah_attr.is_global = 1;
1262 attr.ah_attr.grh.hop_limit = 1;
1263 attr.ah_attr.grh.dgid = remote->pd.ctx.gid;
1264 attr.ah_attr.grh.sgid_index = 0;
1265 }
1266
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001267 attr.ah_attr.dlid = remote->pd.ctx.lid;
1268 attr.ah_attr.sl = 0;
1269 attr.ah_attr.src_path_bits = 0;
1270 attr.ah_attr.port_num = remote->pd.ctx.port_num;
1271 SET(ah, ibv_create_ah(pd.pd, &attr.ah_attr));
1272
1273 memset(&attr, 0, sizeof(attr));
1274 attr.qp_state = IBV_QPS_RTS;
1275 attr.sq_psn = 0;
1276 flags = IBV_QP_STATE | IBV_QP_SQ_PSN;
1277
1278 DO(ibv_modify_qp(qp, &attr, flags));
1279 }
Artemy Kovalyovbe5fe9b2018-02-24 20:51:48 +02001280
1281 virtual int hdr_len() { return 40; }
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001282};
1283
Artemy Kovalyov441bd412018-02-24 20:55:49 +02001284#if HAVE_INFINIBAND_VERBS_EXP_H
Artemy Kovalyovb4f5b672018-10-13 21:35:43 +00001285#define HAVE_DC 1
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001286struct ibvt_dct : public ibvt_obj {
1287 struct ibv_dct *dct;
1288 ibvt_pd &pd;
1289 ibvt_cq &cq;
1290 ibvt_srq &srq;
1291
1292 ibvt_dct(ibvt_env &e, ibvt_pd &p, ibvt_cq &c, ibvt_srq &s) :
1293 ibvt_obj(e), dct(NULL), pd(p), cq(c), srq(s) {}
1294
1295 virtual void init() {
1296 struct ibv_exp_dct_init_attr attr = {};
1297
1298 if (dct)
1299 return;
1300
1301 INIT(pd.init());
1302 INIT(cq.init());
1303 INIT(srq.init());
1304
1305 attr.pd = pd.pd;
1306 attr.cq = cq.cq;
1307 attr.srq = srq.srq;
1308 attr.dc_key = DC_KEY;
1309 attr.port = pd.ctx.port_num;
1310 attr.access_flags = IBV_ACCESS_REMOTE_WRITE;
1311 attr.min_rnr_timer = 2;
1312 attr.mtu = IBV_MTU_512;
1313 attr.hop_limit = 1;
1314 attr.inline_size = 0;
1315 SET(dct, ibv_exp_create_dct(pd.ctx.ctx, &attr));
1316 }
1317
1318 virtual void connect(ibvt_qp *remote) { }
1319
1320 virtual ~ibvt_dct() {
1321 FREE(ibv_exp_destroy_dct, dct);
1322 }
1323};
1324
1325struct ibvt_qp_dc : public ibvt_qp_ud {
1326 ibvt_dct* dremote;
1327
1328 ibvt_qp_dc(ibvt_env &e, ibvt_pd &p, ibvt_cq &c) : ibvt_qp_ud(e, p, c) {}
1329
1330 virtual void init_attr(struct ibv_qp_init_attr_ex &attr) {
1331 ibvt_qp::init_attr(attr);
1332 attr.qp_type = IBV_EXP_QPT_DC_INI;
1333 }
1334
1335 virtual void connect(ibvt_dct *remote) {
1336 struct ibv_exp_qp_attr attr;
1337 long long flags;
1338
1339 this->dremote = remote;
1340
1341 memset(&attr, 0, sizeof(attr));
1342 attr.qp_state = IBV_QPS_INIT;
1343 attr.port_num = pd.ctx.port_num;
1344 attr.pkey_index = 0;
1345 attr.dct_key = DC_KEY;
1346 flags = IBV_EXP_QP_STATE |
1347 IBV_EXP_QP_PKEY_INDEX |
1348 IBV_EXP_QP_PORT |
1349 IBV_EXP_QP_DC_KEY;
1350
1351 DO(ibv_exp_modify_qp(qp, &attr, flags));
1352
1353 memset(&attr, 0, sizeof(attr));
1354 attr.qp_state = IBV_QPS_RTR;
1355 attr.path_mtu = IBV_MTU_512;
1356 attr.ah_attr.is_global = 0;
1357 flags = IBV_EXP_QP_STATE | IBV_EXP_QP_PATH_MTU |
1358 IBV_EXP_QP_AV;
1359
1360
1361 attr.ah_attr.dlid = dremote->pd.ctx.lid;
1362 attr.ah_attr.sl = 0;
1363 attr.ah_attr.src_path_bits = 0;
1364 attr.ah_attr.port_num = dremote->pd.ctx.port_num;
1365 SET(ah, ibv_create_ah(pd.pd, &attr.ah_attr));
1366 DO(ibv_exp_modify_qp(qp, &attr, flags));
1367
1368 memset(&attr, 0, sizeof(attr));
1369 attr.qp_state = IBV_QPS_RTS;
1370 attr.timeout = 14;
1371 attr.retry_cnt = 7;
1372 attr.rnr_retry = 7;
1373 attr.max_rd_atomic = 1;
1374 flags = IBV_EXP_QP_STATE | IBV_EXP_QP_TIMEOUT |
1375 IBV_EXP_QP_RETRY_CNT |
1376 IBV_EXP_QP_RNR_RETRY |
1377 IBV_EXP_QP_MAX_QP_RD_ATOMIC;
1378
1379 DO(ibv_exp_modify_qp(qp, &attr, flags));
1380 }
1381
1382 virtual void post_send(ibv_sge sge, enum ibv_wr_opcode opcode,
1383 int flags = IBV_SEND_SIGNALED) {
1384 struct ibv_sge sge_ud = sge;
1385 struct ibv_exp_send_wr wr = {};
1386 struct ibv_exp_send_wr *bad_wr = NULL;
1387
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001388 wr.sg_list = &sge_ud;
1389 wr.num_sge = 1;
1390 wr.exp_opcode = opcode;
1391 wr.exp_send_flags = flags;
1392
1393 wr.dc.ah = ah;
1394 wr.dc.dct_number = dremote->dct->dct_num;
1395 wr.dc.dct_access_key = DC_KEY;
1396
1397 DO(ibv_exp_post_send(qp, &wr, &bad_wr));
1398 }
Artemy Kovalyova4bd4252017-07-15 12:34:20 +03001399
1400 virtual void rdma(ibv_sge src_sge, ibv_sge dst_sge, enum ibv_wr_opcode opcode, enum ibv_send_flags flags = IBV_SEND_SIGNALED) {
1401 struct ibv_send_wr wr;
1402 struct ibv_send_wr *bad_wr = NULL;
1403
1404 memset(&wr, 0, sizeof(wr));
1405 wr.next = NULL;
1406 wr.wr_id = 0;
1407 wr.sg_list = &src_sge;
1408 wr.num_sge = 1;
1409 wr._wr_opcode = opcode;
1410 wr._wr_send_flags = flags;
1411
1412 wr.dc.ah = ah;
1413 wr.dc.dct_number = dremote->dct->dct_num;
1414 wr.dc.dct_access_key = DC_KEY;
1415
1416 wr.wr.rdma.remote_addr = dst_sge.addr;
1417 wr.wr.rdma.rkey = dst_sge.lkey;
1418
1419 DO(ibv_post_send(qp, &wr, &bad_wr));
1420 }
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001421};
Artemy Kovalyovb4f5b672018-10-13 21:35:43 +00001422
1423
1424#elif HAVE_DECL_MLX5DV_DCTYPE_DCT
Artemy Kovalyovb4f5b672018-10-13 21:35:43 +00001425#define HAVE_DC 1
1426
1427struct ibvt_dct : public ibvt_obj {
1428 struct ibv_qp *dct;
1429 ibvt_pd &pd;
1430 ibvt_cq &cq;
1431 ibvt_srq &srq;
1432
1433 ibvt_dct(ibvt_env &e, ibvt_pd &p, ibvt_cq &c, ibvt_srq &s) :
1434 ibvt_obj(e), dct(NULL), pd(p), cq(c), srq(s) {}
1435
1436 virtual void init() {
1437 struct ibv_qp_attr attr = {};
1438 struct ibv_qp_init_attr_ex init_attr = {};
1439 struct mlx5dv_qp_init_attr dv_attr = {};
1440
1441 if (dct)
1442 return;
1443
1444 INIT(pd.init());
1445 INIT(cq.init());
1446 INIT(srq.init());
1447
1448 init_attr.pd = pd.pd;
1449 init_attr.send_cq = cq.cq;
1450 init_attr.recv_cq = cq.cq;
1451 init_attr.srq = srq.srq;
1452 init_attr.qp_type = IBV_QPT_DRIVER;
1453 init_attr.comp_mask = IBV_QP_INIT_ATTR_PD;
1454
1455 dv_attr.comp_mask = MLX5DV_QP_INIT_ATTR_MASK_DC;
1456 dv_attr.dc_init_attr.dc_type = MLX5DV_DCTYPE_DCT;
1457 dv_attr.dc_init_attr.dct_access_key = DC_KEY;
1458 SET(dct, mlx5dv_create_qp(pd.ctx.ctx, &init_attr, &dv_attr));
1459
1460 attr.qp_state = IBV_QPS_INIT;
1461 attr.port_num = pd.ctx.port_num;
1462 attr.qp_access_flags = IBV_ACCESS_LOCAL_WRITE |
1463 IBV_ACCESS_REMOTE_READ |
1464 IBV_ACCESS_REMOTE_WRITE;
1465
1466 DO(ibv_modify_qp(dct, &attr, IBV_QP_STATE |
1467 IBV_QP_PKEY_INDEX |
1468 IBV_QP_PORT |
1469 IBV_QP_ACCESS_FLAGS));
1470
1471 memset(&attr, 0, sizeof(attr));
1472 attr.qp_state = IBV_QPS_RTR;
1473 attr.path_mtu = IBV_MTU_512;
1474 attr.min_rnr_timer = 2;
1475 attr.ah_attr.grh.hop_limit = 1;
1476 attr.ah_attr.port_num = pd.ctx.port_num;
1477
1478 DO(ibv_modify_qp(dct, &attr, IBV_QP_STATE |
1479 IBV_QP_MIN_RNR_TIMER |
1480 IBV_QP_AV |
1481 IBV_QP_PATH_MTU));
1482 }
1483
1484 virtual void connect(ibvt_qp *remote) { }
1485
1486 virtual ~ibvt_dct() {
1487 FREE(ibv_destroy_qp, dct);
1488 }
1489};
1490
1491struct ibvt_qp_dc : public ibvt_qp_ud {
1492 ibvt_dct* dremote;
Artemy Kovalyovb4f5b672018-10-13 21:35:43 +00001493
1494 ibvt_qp_dc(ibvt_env &e, ibvt_pd &p, ibvt_cq &c) : ibvt_qp_ud(e, p, c) {}
1495
1496 virtual void init() {
1497 struct ibv_qp_init_attr_ex attr = {};
1498 struct mlx5dv_qp_init_attr dv_attr = {};
Artemy Kovalyovb4f5b672018-10-13 21:35:43 +00001499
1500 INIT(pd.init());
1501 INIT(cq.init());
1502
1503 ibvt_qp::init_attr(attr);
1504 attr.qp_type = IBV_QPT_DRIVER;
1505 attr.cap.max_send_wr = 0x40;
1506 attr.cap.max_recv_wr = 0;
1507 attr.cap.max_recv_sge = 0;
1508
1509 dv_attr.comp_mask = MLX5DV_QP_INIT_ATTR_MASK_DC;
1510 dv_attr.dc_init_attr.dc_type = MLX5DV_DCTYPE_DCI;
1511 dv_attr.dc_init_attr.dct_access_key = DC_KEY;
1512 SET(qp, mlx5dv_create_qp(pd.ctx.ctx, &attr, &dv_attr));
1513
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +02001514 EXEC(init_dv());
Artemy Kovalyovb4f5b672018-10-13 21:35:43 +00001515 }
1516
1517 virtual void connect(ibvt_dct *remote) {
1518 struct ibv_qp_attr attr;
1519 long long flags;
1520
1521 this->dremote = remote;
1522
1523 memset(&attr, 0, sizeof(attr));
1524 attr.qp_state = IBV_QPS_INIT;
1525 attr.port_num = pd.ctx.port_num;
1526 attr.pkey_index = 0;
1527 flags = IBV_QP_STATE |
1528 IBV_QP_PKEY_INDEX |
1529 IBV_QP_PORT;
1530
1531 DO(ibv_modify_qp(qp, &attr, flags));
1532
1533 memset(&attr, 0, sizeof(attr));
1534 attr.qp_state = IBV_QPS_RTR;
1535 attr.path_mtu = IBV_MTU_512;
1536 attr.ah_attr.is_global = 0;
1537 flags = IBV_QP_STATE | IBV_QP_PATH_MTU;
1538
1539 attr.ah_attr.dlid = dremote->pd.ctx.lid;
1540 attr.ah_attr.sl = 0;
1541 attr.ah_attr.src_path_bits = 0;
1542 attr.ah_attr.port_num = dremote->pd.ctx.port_num;
1543 SET(ah, ibv_create_ah(pd.pd, &attr.ah_attr));
1544 DO(ibv_modify_qp(qp, &attr, flags));
1545
1546 memset(&attr, 0, sizeof(attr));
1547 attr.qp_state = IBV_QPS_RTS;
1548 attr.timeout = 14;
1549 attr.retry_cnt = 7;
1550 attr.rnr_retry = 7;
1551 attr.max_rd_atomic = 1;
1552 flags = IBV_QP_STATE | IBV_QP_TIMEOUT |
1553 IBV_QP_RETRY_CNT | IBV_QP_SQ_PSN |
1554 IBV_QP_RNR_RETRY |
1555 IBV_QP_MAX_QP_RD_ATOMIC;
1556
1557 DO(ibv_modify_qp(qp, &attr, flags));
1558 }
1559
1560 virtual void post_send(ibv_sge sge, enum ibv_wr_opcode opcode,
1561 int flags = IBV_SEND_SIGNALED) {
1562 uint8_t mac[6] = {}, gid[16] = {};
1563 uint8_t fm_ce_se = 0, op, ds = 5;
1564
1565 if (flags == IBV_SEND_SIGNALED)
1566 fm_ce_se |= MLX5_WQE_CTRL_CQ_UPDATE;
1567 if (opcode == IBV_WR_SEND)
1568 op = MLX5_OPCODE_SEND;
1569 else
1570 FAIL();
1571
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +02001572 struct mlx5_wqe_ctrl_seg *ctrl = (struct mlx5_wqe_ctrl_seg *)get_wqe(0);
Artemy Kovalyovb4f5b672018-10-13 21:35:43 +00001573 mlx5dv_set_ctrl_seg(ctrl, sqi, op, 0, qp->qp_num, fm_ce_se, ds, 0, 0);
1574
1575 struct mlx5_wqe_datagram_seg *avseg = (struct mlx5_wqe_datagram_seg *)(ctrl + 1);
1576 mlx5dv_set_dgram_seg(avseg, DC_KEY, dremote->dct->qp_num, 1, 0,
1577 dremote->pd.ctx.lid, dremote->pd.ctx.lid,
1578 mac, 0, 1, 0, gid);
1579 struct mlx5_wqe_data_seg *dseg = (struct mlx5_wqe_data_seg *)(avseg + 1);
1580 mlx5dv_set_data_seg(dseg, sge.length, sge.lkey, (intptr_t)sge.addr);
1581
Artemy Kovalyovcec4ef92018-12-12 09:41:01 +02001582 ring_db(2);
Artemy Kovalyovb4f5b672018-10-13 21:35:43 +00001583 }
1584
1585 virtual void rdma(ibv_sge src_sge, ibv_sge dst_sge, enum ibv_wr_opcode opcode, enum ibv_send_flags flags = IBV_SEND_SIGNALED) {
1586 FAIL();
1587 }
1588};
1589
Artemy Kovalyov1ccd1a72017-06-02 03:22:22 +03001590#endif
1591
1592template <typename QP>
1593struct ibvt_qp_srq : public QP {
1594 ibvt_srq &srq;
1595
1596 ibvt_qp_srq(ibvt_env &e, ibvt_pd &p, ibvt_cq &c, ibvt_srq &s) :
1597 QP(e, p, c), srq(s) {}
1598
1599 virtual void init_attr(struct ibv_qp_init_attr_ex &attr) {
1600 QP::init_attr(attr);
1601 attr.srq = srq.srq;
1602 }
1603
1604};
1605
Artemy Kovalyov5985a672018-04-28 20:08:24 +00001606#if HAVE_INFINIBAND_VERBS_EXP_H
1607struct ibvt_mw : public ibvt_mr {
1608 ibvt_mr &master;
1609 ibvt_qp &qp;
1610
1611 ibvt_mw(ibvt_mr &i, intptr_t a, size_t size, ibvt_qp &q) :
1612 ibvt_mr(i.env, i.pd, size, a), master(i), qp(q) {}
1613
1614 virtual void init() {
1615 intptr_t addr;
Artemy Kovalyova5bfe6f2018-06-03 17:25:12 +03001616 if (mr || env.skip)
Artemy Kovalyov5985a672018-04-28 20:08:24 +00001617 return;
1618 if (master.buff) {
1619 addr = (intptr_t)master.buff;
1620 buff = master.buff;
1621 } else {
1622 EXEC(init_mmap());
1623 addr = (intptr_t)buff;
1624 }
1625
1626 struct ibv_exp_create_mr_in mr_in = {};
1627 mr_in.pd = pd.pd;
1628 mr_in.attr.create_flags = IBV_EXP_MR_INDIRECT_KLMS;
1629 mr_in.attr.max_klm_list_size = 4;
1630 mr_in.attr.exp_access_flags = IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_READ | IBV_ACCESS_REMOTE_WRITE;
1631 mr_in.comp_mask = 0;
1632 SET(mr, ibv_exp_create_mr(&mr_in));
1633
Artemy Kovalyova5bfe6f2018-06-03 17:25:12 +03001634 if (env.skip)
1635 return;
Artemy Kovalyov5985a672018-04-28 20:08:24 +00001636 struct ibv_exp_mem_region mem_reg = {};
1637 mem_reg.base_addr = addr;
1638 mem_reg.length = size;
1639 mem_reg.mr = master.mr;
1640
1641 struct ibv_exp_send_wr wr = {}, *bad_wr = NULL;
1642 wr.exp_opcode = IBV_EXP_WR_UMR_FILL;
1643 wr.ext_op.umr.umr_type = IBV_EXP_UMR_MR_LIST;
1644 wr.ext_op.umr.exp_access = IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_READ | IBV_ACCESS_REMOTE_WRITE;
1645 wr.ext_op.umr.modified_mr = mr;
1646 wr.ext_op.umr.num_mrs = 1;
1647 wr.ext_op.umr.mem_list.mem_reg_list = &mem_reg;
1648 wr.ext_op.umr.base_addr = addr;
1649 wr.exp_send_flags = IBV_EXP_SEND_INLINE;
1650
1651 DO(ibv_exp_post_send(qp.qp, &wr, &bad_wr));
1652 }
1653};
1654#endif
1655
Artemy Kovalyovea26e1c2016-06-20 17:14:47 +03001656#endif
1657