it almost works... we need to grant more credits...
authorStefan Metzmacher <metze@samba.org>
Wed, 28 Sep 2016 19:56:16 +0000 (21:56 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 1 Jun 2018 12:35:05 +0000 (14:35 +0200)
libcli/smb/smb_direct.c

index ce51679fdcd00ec4561aa25d096d20e4480ead68..91a4e1d1781e29717a007342733f68dba271cda7 100644 (file)
 #include <rdma/rdma_cma.h>
 #include <infiniband/verbs.h>
 
+#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
+
 struct smb_direct_io;
 
 struct smb_direct_connection {
-       struct tevent_context *last_ev;
+       const void *last_ev;
        struct {
                uint32_t max_send_size;
                uint32_t max_receive_size;
@@ -349,10 +351,11 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                io = smb_direct_io_create(c);
                if (io == NULL) {
                        TALLOC_FREE(c);
-DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+DEBUG(0,("%s:%s: SETUP r2s here...\n", __location__, __func__));
                        return NULL;
                }
                DLIST_ADD_END(c->r2s.idle, io);
+DEBUG(0,("%s:%s: SETUP r2s here...\n", __location__, __func__));
        }
 
        for (i = 0; i < c->state.send_credit_target; i++) {
@@ -361,10 +364,11 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                io = smb_direct_io_create(c);
                if (io == NULL) {
                        TALLOC_FREE(c);
-DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+DEBUG(0,("%s:%s: SETUP s2r here...\n", __location__, __func__));
                        return NULL;
                }
                DLIST_ADD_END(c->s2r.idle, io);
+DEBUG(0,("%s:%s: SETUP s2r here...\n", __location__, __func__));
        }
 
 DEBUG(0,("%s:%s: here...\n", __location__, __func__));
@@ -443,6 +447,7 @@ static int smb_direct_connection_post_recv(struct smb_direct_connection *c)
 
 DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        if (c->r2s.idle == NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                return 0;
        }
 
@@ -481,17 +486,23 @@ static int smb_direct_connection_post_send(struct smb_direct_connection *c)
        struct ibv_send_wr *bad_send_wr = NULL;
        int ret;
 
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        if (c->s2r.ready == NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                return 0;
        }
 
        if (c->state.send_credits == 0) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                return 0;
        }
 
+#if 0
        if (1) {
+DEBUG(0,("%s:%s: TODO: REMOVE me ...here...\n", __location__, __func__));
                return 0;
        }
+#endif
 
        for (io = c->s2r.ready; io != NULL; io = next) {
                uint16_t granted = 0;
@@ -507,13 +518,17 @@ static int smb_direct_connection_post_send(struct smb_direct_connection *c)
                c->state.send_credits -= 1;
 
                if (c->state.send_credits == 0) {
-                       flags |= 0x0001;
+                       flags |= SMB_DIRECT_RESPONSE_REQUESTED;
                }
 
                granted = c->state.receive_credit_max;
                granted -= c->state.receive_credits;
                granted = MIN(granted, c->state.receive_credit_target);
                c->state.receive_credits += granted;
+//             if (c->state.receive_credits == 0) {
+//                     granted = 1;
+//                     c->state.receive_credits += granted;
+//             }
 
                if (io->data_length > 0) {
                        data_offset = 0x18;
@@ -534,7 +549,7 @@ static int smb_direct_connection_post_send(struct smb_direct_connection *c)
                SIVAL(io->smbd_hdr, 0x10, io->data_length);
                SIVAL(io->smbd_hdr, 0x14, 0x00000000);
 
-               if (next == NULL) {
+               if (next != NULL) {
                        io->send_wr.next = &next->send_wr;
                } else {
                        io->send_wr.next = NULL;
@@ -547,7 +562,7 @@ static int smb_direct_connection_post_send(struct smb_direct_connection *c)
        last->send_wr.next = NULL;
 
        errno = 0;
-       ret = ibv_post_send(c->ibv.qp, &c->s2r.ready->send_wr, &bad_send_wr);
+       ret = ibv_post_send(c->ibv.qp, &posted->send_wr, &bad_send_wr);
        if (ret != 0) {
                NTSTATUS status;
        //      DLIST_CONCATENATE(c->s2r.ready, posted); // TODO: check bad_send_wr
@@ -562,8 +577,51 @@ static int smb_direct_connection_post_send(struct smb_direct_connection *c)
        return 0;
 }
 
+static int smb_direct_connection_post_keep(struct smb_direct_connection *c)
+{
+       struct smb_direct_io *io = NULL;
+       int ret;
+
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+       if (c->s2r.posted != NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+               return 0;
+       }
+
+       if (c->s2r.ready != NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+               return 0;
+       }
+
+       if (c->s2r.idle == NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+               return 0;
+       }
+
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+       io = c->s2r.idle;
+       DLIST_REMOVE(c->s2r.idle, io);
+
+       io->data_length = 0;
+       io->remaining_length = 0;
+
+       DLIST_ADD_END(c->s2r.ready, io);
+
+       ret = smb_direct_connection_post_send(c);
+       if (ret != 0) {
+               NTSTATUS status;
+               status = map_nt_error_from_unix_common(errno);
+               DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
+                       __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
+               return ret;
+       }
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+
+       return 0;
+}
 static int smb_direct_connection_setup_readv(struct smb_direct_connection *c)
 {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        TEVENT_FD_READABLE(c->sock.fde);
        // TODO: immediate_event?? may skips a syscall.
        return 0;
@@ -571,6 +629,7 @@ static int smb_direct_connection_setup_readv(struct smb_direct_connection *c)
 
 static int smb_direct_connection_setup_writev(struct smb_direct_connection *c)
 {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        TEVENT_FD_WRITEABLE(c->sock.fde);
        // TODO: immediate_event?? may skips a syscall.
        return 0;
@@ -1720,7 +1779,8 @@ static void smb_direct_connection_ibv_handler(struct tevent_context *ev,
 
                        c->r2s.remaining_length -= io->data_length;
 
-                       if (io->remaining_length != c->r2s.remaining_length) {
+                       // Like this???
+                       if (io->remaining_length > c->r2s.remaining_length) {
                                status = NT_STATUS_INVALID_NETWORK_RESPONSE;
                                DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
                                        __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
@@ -1753,15 +1813,17 @@ static void smb_direct_connection_ibv_handler(struct tevent_context *ev,
                }
 
                if (c->state.receive_credits == 0) {
-                       // TODO: send more credits
-                       status = map_nt_error_from_unix_common(errno);
-                       DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
-                               __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
-                       smb_direct_connection_disconnect(c, status);
-                       return;
+                       ret = smb_direct_connection_post_keep(c);
+                       if (ret != 0) {
+                               status = map_nt_error_from_unix_common(errno);
+                               DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
+                                       __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
+                               smb_direct_connection_disconnect(c, status);
+                               return;
+                       }
                }
 
-               if (flags & ~0x0001) {
+               if (flags & ~SMB_DIRECT_RESPONSE_REQUESTED) {
                        status = map_nt_error_from_unix_common(errno);
                        DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
                                __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
@@ -1769,13 +1831,15 @@ static void smb_direct_connection_ibv_handler(struct tevent_context *ev,
                        return;
                }
 
-               if (flags & 0x0001) {
-                       // TODO: send more credits
-                       status = map_nt_error_from_unix_common(errno);
-                       DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
-                               __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
-                       smb_direct_connection_disconnect(c, status);
-                       return;
+               if (flags & SMB_DIRECT_RESPONSE_REQUESTED) {
+                       ret = smb_direct_connection_post_keep(c);
+                       if (ret != 0) {
+                               status = map_nt_error_from_unix_common(errno);
+                               DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
+                                       __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
+                               smb_direct_connection_disconnect(c, status);
+                               return;
+                       }
                }
 
                DLIST_ADD_END(c->r2s.ready, io);
@@ -1814,22 +1878,29 @@ static void smb_direct_connection_sock_handler(struct tevent_context *ev,
        int ret;
        bool ok;
 
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
  do_write:
        if (fde_flags & TEVENT_FD_WRITE) {
                if (c->r2s.out != NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                        io = c->r2s.out;
                } else {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                        io = c->r2s.ready;
-                       DLIST_REMOVE(c->r2s.ready, io);
-                       c->r2s.out = io;
+                       if (io != NULL) {
+                               DLIST_REMOVE(c->r2s.ready, io);
+                               c->r2s.out = io;
+                       }
                }
 
                if (io != NULL) {
                        ssize_t sret;
 
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                        sret = writev(c->sock.fd, io->iov, io->iov_count);
                        if (sret == -1) {
                                if (errno == EAGAIN) { // and more...
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                                        TEVENT_FD_WRITEABLE(c->sock.fde);
                                        goto done_write;
                                }
@@ -1853,14 +1924,17 @@ static void smb_direct_connection_sock_handler(struct tevent_context *ev,
                        if (io->iov_count == 0) {
                                c->r2s.out = NULL;
                                DLIST_ADD_END(c->r2s.idle, io);
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                                goto do_write;
                        }
                } else {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                        TEVENT_FD_NOT_WRITEABLE(c->sock.fde);
                }
        }
 
  done_write:
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        ret = smb_direct_connection_post_recv(c);
        if (ret != 0) {
                status = map_nt_error_from_unix_common(errno);
@@ -1873,49 +1947,57 @@ static void smb_direct_connection_sock_handler(struct tevent_context *ev,
  do_read:
        if (fde_flags & TEVENT_FD_READ) {
                if (c->s2r.in != NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                        io = c->s2r.in;
                } else {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                        io = c->s2r.idle;
-                       DLIST_REMOVE(c->s2r.idle, io);
-                       c->s2r.in = io;
+                       if (io != NULL) {
+                               DLIST_REMOVE(c->s2r.idle, io);
+                               c->s2r.in = io;
 
-                       if (c->s2r.remaining_length > 0) {
-                               /*
-                                * We need to continue to get
-                                * the incomplete packet.
-                                */
-                               io->data_length = MIN(sizeof(io->data),
-                                                     c->s2r.remaining_length);
-                               io->remaining_length = c->s2r.remaining_length;
-                               io->remaining_length -= io->data_length;
-                               c->s2r.remaining_length = io->remaining_length;
-
-                               io->iov = io->_iov_array;
-                               io->iov[0].iov_base = io->data;
-                               io->iov[0].iov_len = io->data_length;
-                               io->iov_count = 1;
-                       } else {
-                               /*
-                                * For a new packet we need to get the length
-                                * first.
-                                */
-                               io->data_length = 0;
-                               io->remaining_length = 0;
+                               if (c->s2r.remaining_length > 0) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+                                       /*
+                                        * We need to continue to get
+                                        * the incomplete packet.
+                                        */
+                                       io->data_length = MIN(sizeof(io->data),
+                                                             c->s2r.remaining_length);
+                                       io->remaining_length = c->s2r.remaining_length;
+                                       io->remaining_length -= io->data_length;
+                                       c->s2r.remaining_length = io->remaining_length;
+
+                                       io->iov = io->_iov_array;
+                                       io->iov[0].iov_base = io->data;
+                                       io->iov[0].iov_len = io->data_length;
+                                       io->iov_count = 1;
+                               } else {
+       DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+                                       /*
+                                        * For a new packet we need to get the length
+                                        * first.
+                                        */
+                                       io->data_length = 0;
+                                       io->remaining_length = 0;
 
-                               io->iov = io->_iov_array;
-                               io->iov[0].iov_base = io->nbt_hdr;
-                               io->iov[0].iov_len = sizeof(io->nbt_hdr);
-                               io->iov_count = 1;
+                                       io->iov = io->_iov_array;
+                                       io->iov[0].iov_base = io->nbt_hdr;
+                                       io->iov[0].iov_len = sizeof(io->nbt_hdr);
+                                       io->iov_count = 1;
+                               }
                        }
                }
                if (io != NULL) {
                        ssize_t sret;
 
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                        sret = readv(c->sock.fd, io->iov, io->iov_count);
                        if (sret == -1) {
                                if (errno == EAGAIN) { // and more...
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                                        TEVENT_FD_READABLE(c->sock.fde);
-                                       goto do_read;
+                                       goto done_read;
                                }
 
                                status = map_nt_error_from_unix_common(errno);
@@ -1943,16 +2025,18 @@ static void smb_direct_connection_sock_handler(struct tevent_context *ev,
 
                        if (io->iov_count == 0) {
                                if (io->data_length != 0) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                                        /*
                                         * We managed to read the whole fragment
                                         * which is ready to be posted into the
                                         * send queue.
                                         */
                                        c->s2r.in = NULL;
-                                       DLIST_ADD_END(c->r2s.ready, io);
+                                       DLIST_ADD_END(c->s2r.ready, io);
                                        goto do_read;
                                }
 
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                                c->s2r.remaining_length = smb_len_tcp(io->nbt_hdr);
                                if (c->s2r.remaining_length > c->state.max_fragmented_size) { //correct direction
                                        status = NT_STATUS_INVALID_BUFFER_SIZE;
@@ -1976,13 +2060,17 @@ static void smb_direct_connection_sock_handler(struct tevent_context *ev,
                                /*
                                 * try to read the reset immediately.
                                 */
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                                goto do_read;
                        }
                } else {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                        TEVENT_FD_NOT_READABLE(c->sock.fde);
                }
        }
 
+ done_read:
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        ret = smb_direct_connection_post_send(c);
        if (ret != 0) {
                status = map_nt_error_from_unix_common(errno);
@@ -1998,7 +2086,9 @@ NTSTATUS smb_direct_connection_setup_events(struct smb_direct_connection *c,
 {
        uint16_t sock_fde_flags = TEVENT_FD_READ;
 
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        if (c->r2s.out != NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                sock_fde_flags |= TEVENT_FD_WRITE;
        }
 
@@ -2007,6 +2097,7 @@ NTSTATUS smb_direct_connection_setup_events(struct smb_direct_connection *c,
                TALLOC_FREE(c->sock.fde);
                TALLOC_FREE(c->ibv.fde_channel);
                TALLOC_FREE(c->rdma.fde_channel);
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        }
 
        if (tevent_fd_get_flags(c->rdma.fde_channel) == 0) {
@@ -2014,18 +2105,25 @@ NTSTATUS smb_direct_connection_setup_events(struct smb_direct_connection *c,
                TALLOC_FREE(c->sock.fde);
                TALLOC_FREE(c->ibv.fde_channel);
                TALLOC_FREE(c->rdma.fde_channel);
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        }
 
        if (ev == NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                c->last_ev = NULL;
                TALLOC_FREE(c->sock.fde);
                TALLOC_FREE(c->ibv.fde_channel);
                TALLOC_FREE(c->rdma.fde_channel);
-       } else if (ev == c->last_ev) {
                return NT_STATUS_OK;
-       } else if (c->last_ev == NULL) {
-               /* fallthrough */
-       } else {
+       }
+
+       if (ev == c->last_ev) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
+               return NT_STATUS_OK;
+       }
+
+       if (c->last_ev != NULL) {
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                return NT_STATUS_INVALID_PARAMETER_MIX;
        }
 
@@ -2056,6 +2154,7 @@ NTSTATUS smb_direct_connection_setup_events(struct smb_direct_connection *c,
                return NT_STATUS_NO_MEMORY;
        }
 
+DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        c->last_ev = ev;
        return NT_STATUS_OK;
 }