more rdma
authorStefan Metzmacher <metze@samba.org>
Sun, 16 Sep 2012 22:33:25 +0000 (00:33 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 18 Sep 2012 03:10:24 +0000 (05:10 +0200)
libcli/smb/smb_transport_direct.c

index d77bc3fd28ddcb90bd763c0843a3ca45082dcec9..4e01ee6312c105eec8fa729d2f1790b69becf55c 100644 (file)
@@ -138,7 +138,7 @@ struct tevent_req *smb_direct_rdma_connect_send(TALLOC_CTX *mem_ctx,
                                        const struct sockaddr_storage *addr,
                                        struct tsocket_address *local_addr,
                                        struct tsocket_address *remote_addr);
-NTSTATUS smb_transport_direct_rdma_connect_recv(struct tevent_req *req);
+NTSTATUS smb_direct_rdma_connect_recv(struct tevent_req *req);
 
 static void smb_direct_rdma_connect_handler(struct tevent_context *ev,
                                            struct tevent_fd *fde,
@@ -308,6 +308,7 @@ static void smb_direct_rdma_connect_handler(struct tevent_context *ev,
                DEBUG(0,("%s:%s: ret[%d] errno[%d]\n",
                        __location__, __FUNCTION__, ret, errno));
 
+               state->t->rdma.expected_event = RDMA_CM_EVENT_DISCONNECTED;
                break;
 
        case RDMA_CM_EVENT_ROUTE_ERROR:
@@ -332,7 +333,7 @@ static void smb_direct_rdma_connect_handler(struct tevent_context *ev,
        }
 }
 
-NTSTATUS smb_transport_direct_rdma_connect_recv(struct tevent_req *req)
+NTSTATUS smb_direct_rdma_connect_recv(struct tevent_req *req)
 {
        struct smb_direct_rdma_connect_state *state =
                tevent_req_data(req,
@@ -350,4 +351,219 @@ NTSTATUS smb_transport_direct_rdma_connect_recv(struct tevent_req *req)
        return NT_STATUS_OK;
 }
 
+struct smb_direct_negotiate_state {
+       struct smb_direct_transport *t;
+};
+
+struct tevent_req *smb_direct_negotiate_send(TALLOC_CTX *mem_ctx,
+                                       struct tevent_context *ev,
+                                       struct smb_direct_transport *transport);
+NTSTATUS smb_direct_negotiate_recv(struct tevent_req *req);
+
+static void smb_direct_negotiate_rdma_handler(struct tevent_context *ev,
+                                             struct tevent_fd *fde,
+                                             uint16_t flags,
+                                             void *private_data);
+static void smb_direct_negotiate_ibv_handler(struct tevent_context *ev,
+                                            struct tevent_fd *fde,
+                                            uint16_t flags,
+                                            void *private_data);
+
+struct tevent_req *smb_direct_negotiate_send(TALLOC_CTX *mem_ctx,
+                                       struct tevent_context *ev,
+                                       struct smb_direct_transport *transport)
+{
+       struct tevent_req *req;
+       struct smb_direct_negotiate_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct smb_direct_negotiate_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->t = transport;
+
+       transport->ibv.fde_channel = tevent_add_fd(ev, transport,
+                                               transport->ibv.comp_channel->fd,
+                                               TEVENT_FD_READ,
+                                               smb_direct_negotiate_ibv_handler,
+                                               req);
+       if (tevent_req_nomem(transport->ibv.fde_channel, req)) {
+               return tevent_req_post(req, ev);
+       }
+       transport->rdma.fde_channel = tevent_add_fd(ev, transport,
+                                               transport->rdma.cm_channel->fd,
+                                               TEVENT_FD_READ,
+                                               smb_direct_negotiate_rdma_handler,
+                                               req);
+       if (tevent_req_nomem(transport->rdma.fde_channel, req)) {
+               return tevent_req_post(req, ev);
+       }
+#if 0
+       cb->recv_mr = ibv_reg_mr(cb->pd, &cb->recv_buf, sizeof cb->recv_buf,
+                                IBV_ACCESS_LOCAL_WRITE);
+       if (!cb->recv_mr) {
+               fprintf(stderr, "recv_buf reg_mr failed\n");
+               return errno;
+       }
+
+       cb->send_mr = ibv_reg_mr(cb->pd, &cb->send_buf, sizeof cb->send_buf, 0);
+       if (!cb->send_mr) {
+               fprintf(stderr, "send_buf reg_mr failed\n");
+               ret = errno;
+               goto err1;
+       }
+
+       cb->rdma_buf = malloc(cb->size);
+       if (!cb->rdma_buf) {
+               fprintf(stderr, "rdma_buf malloc failed\n");
+               ret = -ENOMEM;
+               goto err2;
+       }
+#endif
+       return req;
+}
+
+static void smb_direct_negotiate_ibv_handler(struct tevent_context *ev,
+                                            struct tevent_fd *fde,
+                                            uint16_t flags,
+                                            void *private_data)
+{
+       struct tevent_req *req =
+               talloc_get_type_abort(private_data,
+               struct tevent_req);
+       struct smb_direct_negotiate_state *state =
+               tevent_req_data(req,
+               struct smb_direct_negotiate_state);
+       struct ibv_cq *cq = NULL;
+       void *cq_context = NULL;
+       struct ibv_wc wc;
+       struct ibv_recv_wr *bad_wr;
+       int ret;
+
+       errno = 0;
+
+       ret = ibv_get_cq_event(state->t->ibv.comp_channel,
+                              &cq, &cq_context);
+       if (ret != 0) {
+               DEBUG(0,("%s:%s: ret[%d] errno[%d]\n",
+                       __location__, __FUNCTION__, ret, errno));
+       }
+
+       if (cq != state->t->ibv.cq) {
+       }
+       if (cq_context != state->t) {
+       }
+
+       ret = ibv_req_notify_cq(state->t->ibv.cq, 0);
+       if (ret != 0) {
+               DEBUG(0,("%s:%s: ret[%d] errno[%d]\n",
+                       __location__, __FUNCTION__, ret, errno));
+       }
+
+       ret = ibv_poll_cq(state->t->ibv.cq, 1, &wc);
+       if (ret != 1) {
+       }
+
+       ret = 0;
+
+       if (wc.status != IBV_WC_SUCCESS) {
+       }
+
+       switch (wc.opcode) {
+       case IBV_WC_SEND:
+               break;
+       case IBV_WC_RDMA_WRITE:
+               break;
+       case IBV_WC_RDMA_READ:
+               break;
+       case IBV_WC_RECV:
+               //ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
+               break;
+       default:
+               break;
+       }
+
+       ibv_ack_cq_events(state->t->ibv.cq, 1);
+}
+
+static void smb_direct_negotiate_rdma_handler(struct tevent_context *ev,
+                                             struct tevent_fd *fde,
+                                             uint16_t flags,
+                                             void *private_data)
+{
+       struct tevent_req *req =
+               talloc_get_type_abort(private_data,
+               struct tevent_req);
+       struct smb_direct_negotiate_state *state =
+               tevent_req_data(req,
+               struct smb_direct_negotiate_state);
+       int ret;
+
+       errno = 0;
+
+       ret = rdma_get_cm_event(state->t->rdma.cm_channel,
+                               &state->t->rdma.cm_event);
+       if (ret != 0) {
+               DEBUG(0,("%s:%s: ret[%d] errno[%d]\n",
+                       __location__, __FUNCTION__, ret, errno));
+       }
+
+       if (state->t->rdma.cm_event->status != 0) {
+               DEBUG(0,("%s:%s: ret[%d] errno[%d]\n",
+                       __location__, __FUNCTION__, ret, errno));
+
+       }
+
+       if (state->t->rdma.cm_event->event != state->t->rdma.expected_event) {
+               DEBUG(0,("%s:%s: ret[%d] errno[%d]\n",
+                       __location__, __FUNCTION__, ret, errno));
+
+       }
+
+       switch (state->t->rdma.cm_event->event) {
+       case RDMA_CM_EVENT_ADDR_RESOLVED:
+       case RDMA_CM_EVENT_ADDR_ERROR:
+       case RDMA_CM_EVENT_ROUTE_RESOLVED:
+       case RDMA_CM_EVENT_ESTABLISHED:
+       case RDMA_CM_EVENT_ROUTE_ERROR:
+       case RDMA_CM_EVENT_CONNECT_REQUEST:
+       case RDMA_CM_EVENT_CONNECT_RESPONSE:
+       case RDMA_CM_EVENT_CONNECT_ERROR:
+       case RDMA_CM_EVENT_UNREACHABLE:
+       case RDMA_CM_EVENT_REJECTED:
+       case RDMA_CM_EVENT_DISCONNECTED:
+       case RDMA_CM_EVENT_DEVICE_REMOVAL:
+       case RDMA_CM_EVENT_MULTICAST_JOIN:
+       case RDMA_CM_EVENT_MULTICAST_ERROR:
+       case RDMA_CM_EVENT_ADDR_CHANGE:
+       case RDMA_CM_EVENT_TIMEWAIT_EXIT:
+               //error
+               break;
+       }
+
+       if (state->t->rdma.cm_event != NULL) {
+               rdma_ack_cm_event(state->t->rdma.cm_event);
+               state->t->rdma.cm_event = NULL;
+       }
+}
+
+NTSTATUS smb_direct_rdma_connect_recv(struct tevent_req *req)
+{
+       struct smb_direct_negotiate_state *state =
+               tevent_req_data(req,
+               struct smb_direct_negotiate_state);
+       NTSTATUS status;
+
+       TALLOC_FREE(state->t->ibv.fde_channel);
+       TALLOC_FREE(state->t->rdma.fde_channel);
+
+       if (tevent_req_is_nterror(req, &status)) {
+               tevent_req_received(req);
+               return status;
+       }
+
+       tevent_req_received(req);
+       return NT_STATUS_OK;
+}
 #endif /* SMB_TRANSPORT_ENABLE_RDMA */