@@ -85,7 +85,10 @@ zmq::ctx_t::ctx_t () :
8585 _vmci_fd = -1 ;
8686 _vmci_family = -1 ;
8787#endif
88-
88+ #ifdef ZMQ_HAVE_RDMA
89+ _ib_num_qps = 1 ;
90+ _ib_buf_size = 1024 * 1024 ;
91+ #endif
8992 // Initialise crypto library, if needed.
9093 zmq::random_open ();
9194}
@@ -219,6 +222,9 @@ int zmq::ctx_t::shutdown ()
219222 _sockets[i]->stop ();
220223 if (_sockets.empty ())
221224 _reaper->stop ();
225+ #ifdef ZMQ_HAVE_RDMA
226+ close_ib ();
227+ #endif
222228 }
223229
224230 return 0 ;
@@ -246,8 +252,14 @@ int zmq::ctx_t::set (int option_, int optval_)
246252 } else if (option_ == ZMQ_ZERO_COPY_RECV && optval_ >= 0 ) {
247253 scoped_lock_t locker (_opt_sync);
248254 _zero_copy = (optval_ != 0 );
249- } else if (option_ == ZMQ_ENABLE_RDMA && optval_ >= 0 ) {
250- _rdma_enabled = (optval_ != 0 );
255+ #ifdef ZMQ_HAVE_RDMA
256+ } else if (option_ == ZMQ_IB_NUM_QPS && optval_ >= 0 ) {
257+ scoped_lock_t locker (_opt_sync);
258+ _ib_num_qps = optval_;
259+ } else if (option_ == ZMQ_IB_BUF_SIZE && optval_ >= 0 ) {
260+ scoped_lock_t locker (_opt_sync);
261+ _ib_buf_size = optval_;
262+ #endif
251263 } else {
252264 rc = thread_ctx_t::set (option_, optval_);
253265 }
@@ -271,13 +283,16 @@ int zmq::ctx_t::get (int option_)
271283 rc = _max_msgsz;
272284 else if (option_ == ZMQ_MSG_T_SIZE)
273285 rc = sizeof (zmq_msg_t );
274- else if (option_ == ZMQ_ZERO_COPY_RECV) {
286+ else if (option_ == ZMQ_ZERO_COPY_RECV)
275287 rc = _zero_copy;
276- } else if (option_ == ZMQ_ENABLE_RDMA) {
277- rc = _rdma_enabled;
278- } else {
288+ #ifdef ZMQ_HAVE_RDMA
289+ else if (option_ == ZMQ_IB_NUM_QPS)
290+ rc = _ib_num_qps;
291+ else if (option_ == ZMQ_IB_BUF_SIZE)
292+ rc = _ib_buf_size;
293+ #endif
294+ else
279295 rc = thread_ctx_t::get (option_);
280- }
281296 return rc;
282297}
283298
@@ -340,8 +355,10 @@ bool zmq::ctx_t::start ()
340355 _empty_slots.push_back (i);
341356 }
342357
358+ #ifdef ZMQ_HAVE_RDMA
343359 // RDMA: init ib resources
344- setup_ib (_ib_res, _max_sockets, _max_msgsz);
360+ setup_ib ();
361+ #endif
345362
346363 _starting = false ;
347364 return true ;
@@ -708,3 +725,105 @@ int zmq::ctx_t::get_vmci_socket_family ()
708725// is a global variable. Thus, even sockets created in different contexts have
709726// unique IDs.
710727zmq::atomic_counter_t zmq::ctx_t ::max_socket_id;
728+
729+ #ifdef ZMQ_HAVE_RDMA
730+ #include < infiniband/verbs.h>
731+
732+ int zmq::ctx_t::setup_ib () {
733+ ibv_device **dev_list = NULL ;
734+ memset (&_ib_res, 0 , sizeof (ib_res_t ));
735+
736+ _ib_res.num_qps = get (ZMQ_IB_NUM_QPS);
737+
738+ dev_list =ibv_get_device_list (NULL );
739+ assert (dev_list != NULL );
740+
741+ _ib_res.ctx = ibv_open_device (*dev_list);
742+ assert (_ib_res.ctx != NULL );
743+
744+ _ib_res.pd = ibv_alloc_pd (_ib_res.ctx );
745+ assert (_ib_res.pd != NULL );
746+
747+ int ret = ibv_query_port (_ib_res.ctx , 1 , &_ib_res.port_attr );
748+ assert (ret == 0 );
749+
750+ _ib_res.ib_buf_size = get (ZMQ_IB_BUF_SIZE);
751+ posix_memalign ((void **)_ib_res.ib_buf , 4096 , _ib_res.ib_buf_size );
752+ assert (_ib_res.ib_buf != NULL );
753+
754+ _ib_res.mr = ibv_reg_mr (_ib_res.pd , (void *)_ib_res.ib_buf ,
755+ _ib_res.ib_buf_size ,
756+ IBV_ACCESS_LOCAL_WRITE|
757+ IBV_ACCESS_REMOTE_READ|
758+ IBV_ACCESS_REMOTE_WRITE);
759+ assert (_ib_res.mr != NULL );
760+
761+ ret = ibv_query_device (_ib_res.ctx , &_ib_res.dev_attr );
762+ assert (ret == 0 );
763+
764+ _ib_res.cq = ibv_create_cq (_ib_res.ctx , _ib_res.dev_attr .max_cqe ,
765+ NULL , NULL , 0 );
766+ assert (_ib_res.cq != NULL );
767+
768+ struct ibv_srq_init_attr srq_init_attr;
769+
770+ srq_init_attr.attr .max_wr = _ib_res.dev_attr .max_srq_wr ;
771+ srq_init_attr.attr .max_sge = 1 ;
772+
773+
774+ _ib_res.srq = ibv_create_srq (_ib_res.pd , &srq_init_attr);
775+
776+ struct ibv_qp_init_attr qp_init_attr;
777+
778+ qp_init_attr.send_cq = _ib_res.cq ;
779+ qp_init_attr.recv_cq = _ib_res.cq ;
780+ qp_init_attr.srq = _ib_res.srq ;
781+ qp_init_attr.cap .max_send_wr = _ib_res.dev_attr .max_qp_wr ;
782+ qp_init_attr.cap .max_recv_wr = _ib_res.dev_attr .max_qp_wr ;
783+ qp_init_attr.cap .max_send_sge = 1 ;
784+ qp_init_attr.cap .max_recv_sge = 1 ;
785+ qp_init_attr.qp_type = IBV_QPT_RC;
786+
787+ _ib_res.qp = (struct ibv_qp **) calloc (_ib_res.num_qps ,
788+ sizeof (struct ibv_qp *));
789+ assert (_ib_res.qp != NULL );
790+
791+ for (int i = 0 ; i < _ib_res.num_qps ; i++) {
792+ _ib_res.qp [i] = ibv_create_qp (_ib_res.pd , & qp_init_attr);
793+ assert (_ib_res.qp [i] != NULL );
794+ }
795+
796+ ibv_free_device_list (dev_list);
797+ return 0 ;
798+ }
799+
800+ void zmq::ctx_t::close_ib () {
801+ if (_ib_res.qp != NULL ) {
802+ for (int i = 0 ; i < _ib_res.num_qps ; i++) {
803+ if (_ib_res.qp [i] != NULL ) {
804+ ibv_destroy_qp (_ib_res.qp [i]);
805+ }
806+ }
807+ free (_ib_res.qp );
808+ }
809+
810+ if (_ib_res.srq != NULL )
811+ ibv_destroy_srq (_ib_res.srq );
812+ if (_ib_res.cq != NULL ) {
813+ ibv_destroy_cq (_ib_res.cq );
814+ }
815+ if (_ib_res.mr != NULL ) {
816+ ibv_dereg_mr (_ib_res.mr );
817+ }
818+
819+ if (_ib_res.pd != NULL ) {
820+ ibv_dealloc_pd (_ib_res.pd );
821+ }
822+ if (_ib_res.ctx != NULL ) {
823+ ibv_close_device (_ib_res.ctx );
824+ }
825+ if (_ib_res.ib_buf != NULL ) {
826+ free (_ib_res.ib_buf );
827+ }
828+ }
829+ #endif
0 commit comments