DABC (Data Acquisition Backbone Core)  2.9.9
QueuePair.cxx
Go to the documentation of this file.
1 /************************************************************
2  * The Data Acquisition Backbone Core (DABC) *
3  ************************************************************
4  * Copyright (C) 2009 - *
5  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
6  * Planckstr. 1, 64291 Darmstadt, Germany *
7  * Contact: http://dabc.gsi.de *
8  ************************************************************
9  * This software can be used under the GPL license *
10  * agreements as stated in LICENSE.txt file *
11  * which is part of the distribution. *
12  ************************************************************/
13 
14 #include "verbs/QueuePair.h"
15 
16 #include <netdb.h>
17 #include <cstdlib>
18 #include <cstring>
19 
20 #include "dabc/logging.h"
21 
22 #include "verbs/Device.h"
23 #include "verbs/ComplQueue.h"
24 
25 uint32_t verbs::QueuePair::fQPCounter = 0;
26 
27 // static int __qpcnt__ = 0;
28 
29 verbs::QueuePair::QueuePair(ContextRef ctx, ibv_qp_type qp_type,
30  ComplQueue* send_cq, int send_depth, int max_send_sge,
31  ComplQueue* recv_cq, int recv_depth, int max_recv_sge) :
32  fContext(ctx),
33  fType(qp_type),
34  f_qp(0),
35  f_local_psn(0),
36  f_remote_lid(0),
37  f_remote_qpn(0),
38  f_remote_psn(0),
39  fNumSendSegs(max_send_sge)
40 {
41  if ((send_cq==0) || (recv_cq==0)) {
42  EOUT("No COMPLETION QUEUE WAS SPECIFIED");
43  return;
44  }
45 
46  struct ibv_qp_init_attr attr;
47  memset(&attr, 0, sizeof(struct ibv_qp_init_attr));
48  attr.send_cq = send_cq->cq();
49  attr.recv_cq = recv_cq->cq();
50 // attr.sq_sig_all = 1; // if signal all operation, set 1 ????
51 
52  attr.cap.max_send_wr = send_depth;
53  attr.cap.max_send_sge = max_send_sge;
54 
55  attr.cap.max_recv_wr = recv_depth;
56  attr.cap.max_recv_sge = max_recv_sge;
57 
58  attr.cap.max_inline_data = VERBS_MAX_INLINE;
59  attr.qp_type = fType;
60 
61  f_qp = ibv_create_qp(fContext.pd(), &attr);
62  if (f_qp==0) {
63  EOUT("Couldn't create queue pair (QP)");
64  return;
65  }
66 
67  struct ibv_qp_attr qp_attr;
68  qp_attr.qp_state = IBV_QPS_INIT;
69  qp_attr.pkey_index = 0;
70  qp_attr.port_num = fContext.IbPort();
71  int res = 0;
72 
73  if (qp_type == IBV_QPT_UD) {
74  qp_attr.qkey = VERBS_DEFAULT_QKEY;
75  res = ibv_modify_qp(f_qp, &qp_attr, (ibv_qp_attr_mask)
76  (IBV_QP_STATE |
77  IBV_QP_PKEY_INDEX |
78  IBV_QP_PORT |
79  IBV_QP_QKEY));
80  } else {
81 // qp_attr.qp_access_flags = 0; when no RDMA is required
82 
83  qp_attr.qp_access_flags =
84  IBV_ACCESS_REMOTE_WRITE | IBV_ACCESS_LOCAL_WRITE |
85  IBV_ACCESS_REMOTE_READ;
86  res = ibv_modify_qp(f_qp, &qp_attr, (ibv_qp_attr_mask)
87  (IBV_QP_STATE |
88  IBV_QP_PKEY_INDEX |
89  IBV_QP_PORT |
90  IBV_QP_ACCESS_FLAGS));
91  }
92 
93  if (res!=0) {
94  EOUT("Failed to modify QP to INIT state");
95  return;
96  }
97 
98  fQPCounter += 1;
100 
101  DOUT4("Create QueuePair %p", this);
102 }
103 
105 {
106  DOUT4("Destroy QueuePair %p", this);
107 
108  ibv_destroy_qp(f_qp);
109 
110  DOUT4("Destroy QueuePair %p done", this);
111 }
112 
114 {
115  struct ibv_qp_attr attr;
116  memset(&attr, 0, sizeof attr);
117 
118  attr.qp_state = IBV_QPS_RTR;
119  attr.path_mtu = fContext.mtu();
120 
121  if (ibv_modify_qp(qp(), &attr, IBV_QP_STATE )) {
122  EOUT("Failed to modify UD QP to RTR");
123  return false;
124  }
125 
126  attr.qp_state = IBV_QPS_RTS;
127  attr.sq_psn = local_psn();
128  if (ibv_modify_qp(qp(), &attr, (ibv_qp_attr_mask)
129  (IBV_QP_STATE | IBV_QP_SQ_PSN))) {
130  EOUT("Failed to modify UC/UD QP to RTS");
131  return false;
132  }
133 
134  f_remote_lid = 0;
135  f_remote_qpn = 0;
136  f_remote_psn = 0;
137 
138  return true;
139 }
140 
141 bool verbs::QueuePair::Connect(uint16_t dest_lid, uint32_t dest_qpn, uint32_t dest_psn, uint8_t src_path_bits)
142 {
143  if (qp_type() == IBV_QPT_UD) {
144  EOUT("QueuePair::Connect not supported for unreliable datagram connection. Use InitUD() instead");
145  return false;
146  }
147 
148  DOUT3("Start QP connect with %x:%x:%x", dest_lid, dest_qpn, dest_psn);
149 
150  struct ibv_qp_attr attr;
151  memset(&attr, 0, sizeof attr);
152 
153  attr.qp_state = IBV_QPS_RTR;
154  attr.path_mtu = fContext.mtu();
155 
156 /*
157  switch (f_mtu) {
158  case 256: attr.path_mtu = IBV_MTU_256; break;
159  case 512: attr.path_mtu = IBV_MTU_512; break;
160  case 1024: attr.path_mtu = IBV_MTU_1024; break;
161  case 2048: attr.path_mtu = IBV_MTU_2048; break;
162  case 4096: attr.path_mtu = IBV_MTU_4096; break;
163  default: EOUT("Wrong mtu value %u", f_mtu);
164  }
165 */
166 
167 // FIXME: why mtu was fixed to 1024
168 // attr.path_mtu = IBV_MTU_1024;
169 
170  attr.dest_qp_num = dest_qpn;
171  attr.rq_psn = dest_psn;
172  if (qp_type() == IBV_QPT_RC) {
173  attr.max_dest_rd_atomic = 1;
174  attr.min_rnr_timer = 12;
175  }
176 
177  attr.ah_attr.is_global = 0;
178  attr.ah_attr.dlid = dest_lid;
179  attr.ah_attr.sl = 0;
180  // DOUT0("Configure static rate");
181  // attr.ah_attr.static_rate = 3 /*IBV_RATE_5_GBPS*/; // SL: no idea how static rate works
182  attr.ah_attr.src_path_bits = src_path_bits;
183  attr.ah_attr.port_num = fContext.IbPort();
184 
185  DOUT3("Modify to RTR");
186 
187  if (qp_type() == IBV_QPT_RC) {
188  if (ibv_modify_qp(qp(), &attr, (ibv_qp_attr_mask)
189  (IBV_QP_STATE |
190  IBV_QP_AV |
191  IBV_QP_PATH_MTU |
192  IBV_QP_DEST_QPN |
193  IBV_QP_RQ_PSN |
194  IBV_QP_MIN_RNR_TIMER |
195  IBV_QP_MAX_DEST_RD_ATOMIC))) {
196  EOUT("Failed here to modify RC QP to RTR lid: %x, qpn: %x, psn:%x", dest_lid, dest_qpn, dest_psn);
197  return false;
198  }
199  } else
200 
201  if (qp_type() == IBV_QPT_UC) {
202  if (ibv_modify_qp(qp(), &attr, (ibv_qp_attr_mask)
203  (IBV_QP_STATE |
204  IBV_QP_AV |
205  IBV_QP_PATH_MTU |
206  IBV_QP_DEST_QPN |
207  IBV_QP_RQ_PSN))) {
208  EOUT("Failed to modify UC QP to RTR");
209  return false;
210  }
211  } else
212 
213  if (qp_type() == IBV_QPT_UD) {
214  if (ibv_modify_qp(qp(), &attr,
215  IBV_QP_STATE )) {
216  EOUT("Failed to modify UD QP to RTR");
217  return false;
218  }
219  }
220 
221  DOUT3("Modify to RTS");
222 
223  attr.qp_state = IBV_QPS_RTS;
224  attr.sq_psn = local_psn();
225  if (qp_type() == IBV_QPT_RC) {
226  attr.timeout = 14;
227  attr.retry_cnt = 7;
228  attr.rnr_retry = 7;
229  attr.max_rd_atomic = 1;
230  if (ibv_modify_qp(qp(), &attr, (ibv_qp_attr_mask)
231  (IBV_QP_STATE |
232  IBV_QP_SQ_PSN |
233  IBV_QP_TIMEOUT |
234  IBV_QP_RETRY_CNT |
235  IBV_QP_RNR_RETRY |
236  IBV_QP_MAX_QP_RD_ATOMIC))) {
237  EOUT("Failed to modify RC QP to RTS");
238  return false;
239  }
240  } else { /*both UC and UD */
241  if (ibv_modify_qp(qp(), &attr, (ibv_qp_attr_mask)
242  (IBV_QP_STATE |
243  IBV_QP_SQ_PSN))) {
244  EOUT("Failed to modify UC/UD QP to RTS");
245  return false;
246  }
247  }
248 
249  f_remote_lid = dest_lid;
250  f_remote_qpn = dest_qpn;
251  f_remote_psn = dest_psn;
252 
253  DOUT3("QP connected !!!");
254 
255 // if (qp_type()!= IBV_QPT_UD)
256 // DOUT1("DO CONNECT local_qpn=%x remote_qpn=%x", qp_num(), dest_qpn);
257 
258  return true;
259 }
260 
261 bool verbs::QueuePair::Post_Send(struct ibv_send_wr* swr)
262 {
263  struct ibv_send_wr* bad_swr = 0;
264 
265  if (ibv_post_send(qp(), swr, &bad_swr)) {
266  EOUT("ibv_post_send fails arg %lx", bad_swr->wr_id);
267  return false;
268  }
269 
270  return true;
271 }
272 
273 bool verbs::QueuePair::Post_Recv(struct ibv_recv_wr* rwr)
274 {
275  struct ibv_recv_wr* bad_rwr = 0;
276 
277  if (ibv_post_recv(qp(), rwr, &bad_rwr)) {
278  EOUT("ibv_post_recv fails arg = %lx", bad_rwr->wr_id);
279  return false;
280  }
281 
282  return true;
283 }
284 
285 bool verbs::QueuePair::AttachMcast(ibv_gid* mgid, uint16_t mlid)
286 {
287  return ibv_attach_mcast(qp(), mgid, mlid) == 0;
288 }
289 
290 bool verbs::QueuePair::DetachMcast(ibv_gid* mgid, uint16_t mlid)
291 {
292  return ibv_detach_mcast(qp(), mgid, mlid) == 0;
293 }
#define VERBS_MAX_INLINE
Definition: QueuePair.h:17
#define VERBS_DEFAULT_QKEY
Definition: QueuePair.h:18
Wrapper for IB VERBS completion queue
Definition: ComplQueue.h:35
struct ibv_cq * cq() const
Definition: ComplQueue.h:56
Reference to verbs::Context
Definition: Context.h:74
struct ibv_pd * pd() const
Definition: Context.h:86
int IbPort() const
Definition: Context.h:84
ContextRef fContext
Definition: QueuePair.h:79
QueuePair(ContextRef ctx, ibv_qp_type qp_type, ComplQueue *send_cq, int send_depth, int max_send_sge, ComplQueue *recv_cq, int recv_depth, int max_recv_sge)
Definition: QueuePair.cxx:29
static uint32_t fQPCounter
Definition: QueuePair.h:77
ibv_qp_type fType
Definition: QueuePair.h:81
bool InitUD()
Initialize QP for unreliable datagram protocol.
Definition: QueuePair.cxx:113
bool Post_Send(struct ibv_send_wr *swr)
Definition: QueuePair.cxx:261
bool Post_Recv(struct ibv_recv_wr *rwr)
Definition: QueuePair.cxx:273
ibv_qp_type qp_type() const
Definition: QueuePair.h:46
bool DetachMcast(ibv_gid *mgid, uint16_t mlid)
Definition: QueuePair.cxx:290
bool AttachMcast(ibv_gid *mgid, uint16_t mlid)
Definition: QueuePair.cxx:285
virtual ~QueuePair()
Definition: QueuePair.cxx:104
uint32_t f_local_psn
number used in connection
Definition: QueuePair.h:85
struct ibv_qp * f_qp
Definition: QueuePair.h:83
bool Connect(uint16_t lid, uint32_t qpn, uint32_t psn, uint8_t src_path_bits=0)
Connect QP to specified remote queue pair.
Definition: QueuePair.cxx:141
#define DOUT3(args ...)
Definition: logging.h:176
#define EOUT(args ...)
Definition: logging.h:150
#define DOUT4(args ...)
Definition: logging.h:182