more
authorStefan Metzmacher <metze@samba.org>
Fri, 30 Sep 2016 13:52:03 +0000 (15:52 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 1 Jun 2018 12:35:11 +0000 (14:35 +0200)
libcli/smb/smb_direct.c
libcli/smb/smb_direct.h
libcli/smb/smb_direct_daemon.c

index b4bf7b96ccade9b8a2ac42916a1b2dd83ebe5192..0111e4e9ec1432ed7e6b2d8acd634fcf24abb49f 100644 (file)
 #include <rdma/rdma_cma.h>
 #include <infiniband/verbs.h>
 
+#define SMB_DIRECT_LISTENER_BACKLOG 100
+
+//#define SMB_DIRECT_IO_MAX_DATA 8192
+#define SMB_DIRECT_IO_MAX_DATA 1364
+#define SMB_DIRECT_DATA_MIN_HDR_SIZE 0x14
+#define SMB_DIRECT_DATA_OFFSET NDR_ROUND(SMB_DIRECT_DATA_MIN_HDR_SIZE, 8)
+
 #define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
 
+struct smb_direct_listener;
+struct smb_direct_connection;
 struct smb_direct_io;
 
 struct smb_direct_listener {
+       struct tevent_context *ev;
        struct {
                struct smb_direct_rdma_context context;
                struct rdma_cm_id *cm_id;
@@ -47,9 +57,13 @@ struct smb_direct_listener {
                enum rdma_cm_event_type expected_event;
                struct rdma_cm_event *cm_event;
        } rdma;
+       struct smb_direct_connection *ready;
 };
 
 struct smb_direct_connection {
+       struct smb_direct_connection *next, *prev; /* used in the listener ready list */
+       struct smb_direct_listener *l; /* only valid before fully accepted */
+
        const void *last_ev;
        struct {
                uint32_t max_send_size;
@@ -114,10 +128,6 @@ struct smb_direct_connection {
 
 struct smb_direct_connection *smb_direct_conn;
 
-//#define SMB_DIRECT_IO_MAX_DATA 8192
-#define SMB_DIRECT_IO_MAX_DATA 1364
-#define SMB_DIRECT_DATA_MIN_HDR_SIZE 0x14
-#define SMB_DIRECT_DATA_OFFSET NDR_ROUND(SMB_DIRECT_DATA_MIN_HDR_SIZE, 8)
 
 struct smb_direct_io {
        struct smb_direct_io *prev, *next;
@@ -286,7 +296,7 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        return c;
 }
 
-NTSTATUS smb_direct_connection_complete_alloc(struct smb_direct_connection *c)
+static NTSTATUS smb_direct_connection_complete_alloc(struct smb_direct_connection *c)
 {
        int ret;
        uint16_t i;
@@ -395,6 +405,11 @@ static void smb_direct_connection_debug_credits(struct smb_direct_connection *c,
 
 static int smb_direct_connection_destructor(struct smb_direct_connection *c)
 {
+       if (c->l != NULL) {
+               DLIST_REMOVE(c->l->ready, c);
+               c->l = NULL;
+       }
+
        TALLOC_FREE(c->sock.fde);
 
        if (c->sock.fd != -1) {
@@ -738,7 +753,7 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                return tevent_req_post(req, ev);
        }
 
-       c->rdma.fde_channel = tevent_add_fd(ev, c,
+       c->rdma.fde_channel = tevent_add_fd(ev, state,
                                        c->rdma.cm_channel->fd,
                                        TEVENT_FD_READ,
                                        smb_direct_connection_rdma_connect_handler,
@@ -969,14 +984,16 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        // TODO: cleanup
        talloc_set_destructor(state, smb_direct_connection_negotiate_connect_destructor);
 
-       c->rdma.fde_channel = tevent_add_fd(ev, c, c->rdma.cm_channel->fd,
+       c->rdma.fde_channel = tevent_add_fd(ev, state,
+                                           c->rdma.cm_channel->fd,
                                            TEVENT_FD_READ,
                                            smb_direct_connection_negotiate_connect_rdma_handler,
                                            req);
        if (tevent_req_nomem(c->rdma.fde_channel, req)) {
                return tevent_req_post(req, ev);
        }
-       c->ibv.fde_channel = tevent_add_fd(ev, c, c->ibv.comp_channel->fd,
+       c->ibv.fde_channel = tevent_add_fd(ev, state,
+                                          c->ibv.comp_channel->fd,
                                           TEVENT_FD_READ,
                                           smb_direct_connection_negotiate_connect_ibv_handler,
                                           req);
@@ -2179,64 +2196,6 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        return NT_STATUS_OK;
 }
 
-struct smb_direct_connection *smb_direct_connection_listener(
-       TALLOC_CTX *mem_ctx,
-       struct rdma_cm_id *cm_id)
-{
-       struct smb_direct_connection *c;
-       int sfd[2];
-       int ret;
-       //uint16_t i;
-
-       c = talloc_zero(mem_ctx, struct smb_direct_connection);
-       if (c == NULL) {
-               return NULL;
-       }
-       c->sock.fd = -1;
-       c->sock.tmp_fd = -1;
-//DEBUG(0,("%s:%s: here...\n", __location__, __func__));
-       talloc_set_destructor(c, smb_direct_connection_destructor);
-
-       c->state.max_send_size       = 1364;
-       c->state.max_receive_size    = SMB_DIRECT_IO_MAX_DATA;
-       c->state.max_fragmented_size = 1048576;
-       c->state.max_read_write_size = 0;
-       c->state.receive_credit_max  = 10;//255;
-       c->state.send_credit_target  = 255;
-       c->state.keep_alive_internal = 5;
-
-       ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sfd);
-       if (ret == -1) {
-               int saved_errno = errno;
-               TALLOC_FREE(c);
-DEBUG(0,("%s:%s: here...\n", __location__, __func__));
-               errno = saved_errno;
-               return NULL;
-       }
-       c->sock.tmp_fd = sfd[0];
-       c->sock.fd = sfd[1];
-
-DEBUG(0,("%s:%s: sock.fd[%d] sock.tmp_fd[%d]\n",
-       __location__, __func__, c->sock.fd, c->sock.tmp_fd));
-
-       smb_set_close_on_exec(c->sock.tmp_fd);
-       smb_set_close_on_exec(c->sock.fd);
-       set_blocking(c->sock.fd, false);
-
-       c->rdma.cm_channel = rdma_create_event_channel();
-       if (c->rdma.cm_channel == NULL) {
-               TALLOC_FREE(c);
-DEBUG(0,("%s:%s: here...\n", __location__, __func__));
-               return NULL;
-       }
-       smb_set_close_on_exec(c->rdma.cm_channel->fd);
-       set_blocking(c->rdma.cm_channel->fd, false);
-
-       c->rdma.cm_id = cm_id;
-
-       return c;
-}
-
 uint32_t smb_direct_connection_max_fragmented_size(struct smb_direct_connection *c)
 {
        return c->state.max_fragmented_size;
@@ -2251,12 +2210,13 @@ static int smb_direct_listener_destructor(struct smb_direct_listener *l);
 
 NTSTATUS smbd_direct_listener_setup(TALLOC_CTX *mem_ctx,
                                    const struct sockaddr_storage *addr,
-                                   struct smb_direct_listener **_l);
+                                   struct smb_direct_listener **_l)
 {
        struct smb_direct_listener *l;
        int ret;
        struct sockaddr_storage _addr = *addr;
        struct sockaddr *bind_addr = (struct sockaddr *)&_addr;
+       char addr_buf[INET6_ADDRSTRLEN] = { 0, };
 
        set_sockaddr_port(bind_addr, 5445);
 
@@ -2276,7 +2236,7 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
        smb_set_close_on_exec(l->rdma.cm_channel->fd);
        set_blocking(l->rdma.cm_channel->fd, false);
 
-       l->rdma.context.c = l;
+       l->rdma.context.l = l;
 #if RDMA_USER_CM_MAX_ABI_VERSION >= 2
        ret = rdma_create_id(l->rdma.cm_channel,
                             &l->rdma.cm_id,
@@ -2306,7 +2266,7 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                return status;
        }
 
-       ret = rdma_listen(l->rdma.cm_id, SMB_DIRECT_LISTEN_BACKLOG);
+       ret = rdma_listen(l->rdma.cm_id, SMB_DIRECT_LISTENER_BACKLOG);
        if (ret != 0) {
                NTSTATUS status;
                status = map_nt_error_from_unix_common(errno);
@@ -2314,7 +2274,10 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
 DEBUG(0,("%s:%s: here...\n", __location__, __func__));
                return status;
        }
-       c->rdma.expected_event = RDMA_CM_EVENT_ADDR_RESOLVED;
+       l->rdma.expected_event = RDMA_CM_EVENT_CONNECT_REQUEST;
+
+       DBG_ERR("SMB-D daemon started listening SMB-D connections on listener[%p]: %s\n",
+               l, print_sockaddr(addr_buf, sizeof(addr_buf), &_addr));
 
        *_l = l;
        return NT_STATUS_OK;
@@ -2322,46 +2285,90 @@ DEBUG(0,("%s:%s: here...\n", __location__, __func__));
 
 static int smb_direct_listener_destructor(struct smb_direct_listener *l)
 {
-       TALLOC_FREE(c->rdma.fde_channel);
+       TALLOC_FREE(l->rdma.fde_channel);
 
-       if (c->rdma.cm_event != NULL) {
-               rdma_ack_cm_event(c->rdma.cm_event);
-               c->rdma.cm_event = NULL;
+       if (l->rdma.cm_event != NULL) {
+               rdma_ack_cm_event(l->rdma.cm_event);
+               l->rdma.cm_event = NULL;
        }
 
-       if (c->rdma.cm_id != NULL) {
-               rdma_destroy_id(c->rdma.cm_id);
-               c->rdma.cm_id = NULL;
+       if (l->rdma.cm_id != NULL) {
+               rdma_destroy_id(l->rdma.cm_id);
+               l->rdma.cm_id = NULL;
        }
 
-       if (c->rdma.cm_channel != NULL) {
-               rdma_destroy_event_channel(c->rdma.cm_channel);
-               c->rdma.cm_channel = NULL;
+       if (l->rdma.cm_channel != NULL) {
+               rdma_destroy_event_channel(l->rdma.cm_channel);
+               l->rdma.cm_channel = NULL;
        }
 
        return 0;
 }
 
+struct smb_direct_listener_accept_state {
+       struct tevent_context *ev;
+       struct smb_direct_listener *l;
+};
+
+static int smb_direct_listener_accept_state_destructor(
+               struct smb_direct_listener_accept_state *state)
+{
+       TALLOC_FREE(state->l->rdma.fde_channel);
+
+       return 0;
+}
+
+static void smb_direct_listener_accept_rdma_handler(struct tevent_context *ev,
+                                                   struct tevent_fd *fde,
+                                                   uint16_t flags,
+                                                   void *private_data);
+
 struct tevent_req *smb_direct_listener_accept_send(TALLOC_CTX *mem_ctx,
                                                   struct tevent_context *ev,
                                                   struct smb_direct_listener *l)
 {
-       struct tevent_req
+       struct tevent_req *req = NULL;
+       struct smb_direct_listener_accept_state *state = NULL;
 
-static void smb_direct_listener_rdma_handler(struct tevent_context *ev,
-                                            struct tevent_fd *fde,
-                                            uint16_t flags,
-                                            void *private_data)
+       req = tevent_req_create(mem_ctx, &state,
+                               struct smb_direct_listener_accept_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->l = l;
+       talloc_set_destructor(state, smb_direct_listener_accept_state_destructor);
+
+       l->rdma.fde_channel = tevent_add_fd(ev, state,
+                                       l->rdma.cm_channel->fd,
+                                       TEVENT_FD_READ,
+                                       smb_direct_listener_accept_rdma_handler,
+                                       req);
+       if (tevent_req_nomem(l->rdma.fde_channel, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       DBG_ERR("SMB-D daemon started accepting SMB-D connections on listener[%p]\n", l);
+
+       return req;
+}
+
+static void smb_direct_listener_accept_rdma_handler(struct tevent_context *ev,
+                                                   struct tevent_fd *fde,
+                                                   uint16_t flags,
+                                                   void *private_data)
 {
-       struct smb_direct_listener *l =
+       struct tevent_req *req =
                talloc_get_type_abort(private_data,
-               struct smb_direct_listener);
-       struct rdma_cm_event *cm_ev = NULL;
-       struct rdma_cm_event cm_ev_copy;
-       int result;
+               struct tevent_req);
+       struct smb_direct_listener_accept_state *state =
+               tevent_req_data(req,
+               struct smb_direct_listener_accept_state);
+       struct smb_direct_listener *l = state->l;
        NTSTATUS status;
+       int ret;
 
-       DBG_ERR("SMB-D got connection event\n");
+       DBG_ERR("SMB-D got connection event listener[%p]\n", l);
 
        ret = rdma_get_cm_event(l->rdma.cm_channel,
                                &l->rdma.cm_event);
@@ -2370,87 +2377,184 @@ static void smb_direct_listener_rdma_handler(struct tevent_context *ev,
                DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
                        __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
                smb_direct_listener_destructor(l); //TODO cleanup???
+               tevent_req_nterror(req, status);
                return;
        }
 
        errno = 0;
-       if (c->rdma.cm_event->status != 0) {
-               errno = c->rdma.cm_event->status;
+       if (l->rdma.cm_event->status != 0) {
+               errno = l->rdma.cm_event->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)));
                smb_direct_listener_destructor(l); //TODO cleanup???
+               tevent_req_nterror(req, status);
                return;
        }
 
-       if (c->rdma.cm_event->event != c->rdma.expected_event) {
-               DEBUG(0,("%s:%s: c->rdma.cm_event->event[%u] != c->rdma.expected_event[%u]\n",
+       if (l->rdma.cm_event->event != l->rdma.expected_event) {
+               DEBUG(0,("%s:%s: l->rdma.cm_event->event[%u] != l->rdma.expected_event[%u]\n",
                        __location__, __FUNCTION__,
-                       c->rdma.cm_event->event, c->rdma.expected_event));
+                       l->rdma.cm_event->event, l->rdma.expected_event));
        }
 
-       switch (c->rdma.cm_event->event) {
+       switch (l->rdma.cm_event->event) {
        case RDMA_CM_EVENT_ADDR_RESOLVED:
                DBG_DEBUG("RDMA_CM_EVENT_ADDR_RESOLVED\n");
 
                errno = 0;
-               ret = rdma_resolve_route(c->rdma.cm_id, 5000);
+               ret = rdma_resolve_route(l->rdma.cm_id, 5000);
                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_listener_destructor(l); //TODO cleanup???
+                       tevent_req_nterror(req, status);
                        return;
                }
-               c->rdma.expected_event = RDMA_CM_EVENT_ROUTE_RESOLVED;
-               break;
-       case RDMA_CM_EVENT_CONNECT_REQUEST:
+               l->rdma.expected_event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+               smb_direct_listener_destructor(l); //TODO cleanup???
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return;
+
+       case RDMA_CM_EVENT_CONNECT_REQUEST: {
+               struct rdma_conn_param conn_param;
+               uint8_t ird_ord_hdr[8];
+               struct smb_direct_connection *c = NULL;
+
+               RSIVAL(ird_ord_hdr, 0, 0);
+               RSIVAL(ird_ord_hdr, 4, 16);
+
                DBG_DEBUG("RDMA_CM_EVENT_CONNECT_REQUEST\n");
 
-               result = rdma_accept(cm_ev_copy.id, NULL);
-               if (result != 0) {
-                       DBG_ERR("rdma_accept failed [%s]\n", strerror(errno));
-                       goto fail;
+               conn_param = l->rdma.cm_event->param.conn;
+//             ZERO_STRUCT(conn_param);
+               conn_param.private_data = ird_ord_hdr;
+               conn_param.private_data_len = sizeof(ird_ord_hdr);
+//             conn_param.responder_resources = 1;
+//             conn_param.initiator_depth = 1;
+//             conn_param.retry_count = 10;
+
+               c = smb_direct_connection_create(l);
+               if (c == NULL) {
+                       DBG_ERR("smb_direct_connection_create failed - ignoring\n");
+
+                       rdma_reject(l->rdma.cm_event->id, NULL, 0);
+                       /* wait for more */
+                       break;
                }
 
-               sconn = smb_direct_connection_listener(daemon_state,
-                                                      cm_ev_copy.id);
-               if (sconn == NULL) {
-                       DBG_ERR("smb_direct_connection_create failed\n");
-                       return;
+               c->rdma.cm_id = l->rdma.cm_event->id;
+               c->rdma.cm_id->context = &c->rdma.context;
+               c->rdma.cm_id->channel = c->rdma.cm_channel;
+
+               status = smb_direct_connection_complete_alloc(c);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DBG_ERR("smb_direct_connection_complete_alloc failed - ignoring\n");
+                       c->rdma.cm_id->context = NULL;
+                       c->rdma.cm_id->channel = NULL;
+                       c->rdma.cm_id = NULL;
+                       TALLOC_FREE(c);
+
+                       rdma_reject(l->rdma.cm_event->id, NULL, 0);
+                       /* wait for more */
+                       break;
+               }
+
+               ret = rdma_accept(c->rdma.cm_id, &conn_param);
+               if (ret != 0) {
+                       DBG_ERR("rdma_accept failed [%s] result [%d]\n", strerror(errno), ret);
+                       c->rdma.cm_id->context = NULL;
+                       c->rdma.cm_id->channel = NULL;
+                       c->rdma.cm_id = NULL;
+                       TALLOC_FREE(c);
+
+                       //??? rdma_reject(l->rdma.cm_event->id);
+                       /* wait for more */
+                       break;
                }
 
-               cm_ev_copy.id->context = sconn;
+               l->rdma.cm_event->id = NULL;
+
+               c->l = l;
+               DLIST_ADD_END(l->ready, c);
+
+               tevent_req_defer_callback(req, l->ev);
+               tevent_req_done(req);
+               }
                break;
 
        case RDMA_CM_EVENT_DISCONNECTED:
                DBG_DEBUG("RDMA_CM_EVENT_DISCONNECTED\n");
-
-               sconn = talloc_get_type(cm_ev_copy.id->context,
-                                       struct smb_direct_connection);
-               TALLOC_FREE(sconn);
                break;
 
        case RDMA_CM_EVENT_DEVICE_REMOVAL:
                DBG_ERR("RDMA device removal\n");
-               goto fail;
+               break;
 
        default:
-               DBG_ERR("event %d\n", cm_ev_copy.event);
-               goto fail;
+               DBG_ERR("event %d\n", l->rdma.cm_event->event);
+               break;
        }
 
+       rdma_ack_cm_event(l->rdma.cm_event);
+       l->rdma.cm_event = NULL;
 
        return;
+}
 
-fail:
-       if (cm_ev_copy.id == daemon_state->rdma.cm_id) {
-               /* Listening conn is erroring out, shut it down and die */
-               TALLOC_FREE(daemon_state->listening_conn);
+NTSTATUS smb_direct_listener_accept_recv(struct tevent_req *req,
+                                        TALLOC_CTX *mem_ctx,
+                                        struct smb_direct_connection **_c,
+                                        int *fd,
+                                        struct sockaddr_storage *laddr,
+                                        struct sockaddr_storage *raddr)
+{
+       struct smb_direct_listener_accept_state *state =
+               tevent_req_data(req,
+               struct smb_direct_listener_accept_state);
+       struct smb_direct_listener *l = state->l;
+       struct smb_direct_connection *c = NULL;
+       NTSTATUS status;
+
+       *_c = NULL;
+       *fd = -1;
+       if (laddr != NULL) {
+               ZERO_STRUCTP(laddr);
+       }
+       if (raddr != NULL) {
+               ZERO_STRUCTP(raddr);
        }
 
-       TALLOC_FREE(sconn);
-       return;
+       if (tevent_req_is_nterror(req, &status)) {
+               tevent_req_received(req);
+               return status;
+       }
+
+       /*
+        * We don't call tevent_req_received()
+        * because the caller can lease this alive
+        * in order to consume more connections
+        */
+       if (l->ready == NULL) {
+               return NT_STATUS_NO_MORE_ENTRIES;
+       }
+
+       c = l->ready;
+       DLIST_REMOVE(l->ready, c);
+       c->l = NULL;
+
+       *fd = c->sock.tmp_fd;
+       c->sock.tmp_fd = -1;
+       if (laddr != NULL) {
+               ZERO_STRUCTP(laddr);
+       }
+       if (raddr != NULL) {
+               ZERO_STRUCTP(raddr);
+       }
+       *_c = talloc_move(mem_ctx, &c);
+       return NT_STATUS_OK;
+
 }
 
 #endif /* SMB_TRANSPORT_ENABLE_RDMA */
index 3dda5986af32ee0510694c83622773219e3b22c0..62e15eaa082cc073249bda6b57835a81bf13e3ad 100644 (file)
@@ -33,19 +33,32 @@ struct smb_direct_rdma_context {
        struct smb_direct_listener *l;
 };
 
+//struct smb_direct_connection_list {
+//     struct smb_direct_connection *list;
+//};
+
 //Hack...
 extern struct smb_direct_connection *smb_direct_conn;
 
-struct smb_direct_connection *smb_direct_connection_create(TALLOC_CTX *mem_ctx);
-struct smb_direct_connection *smb_direct_connection_listener(TALLOC_CTX *mem_ctx,
-                                                            struct rdma_cm_id *cm_id);
-NTSTATUS smb_direct_connection_complete_alloc(struct smb_direct_connection *c);
+NTSTATUS smbd_direct_listener_setup(TALLOC_CTX *mem_ctx,
+                                   const struct sockaddr_storage *addr,
+                                   struct smb_direct_listener **_l);
+struct tevent_req *smb_direct_listener_accept_send(TALLOC_CTX *mem_ctx,
+                                                  struct tevent_context *ev,
+                                                  struct smb_direct_listener *l);
+NTSTATUS smb_direct_listener_accept_recv(struct tevent_req *req,
+                                        TALLOC_CTX *mem_ctx,
+                                        struct smb_direct_connection **_c,
+                                        int *fd,
+                                        struct sockaddr_storage *laddr,
+                                        struct sockaddr_storage *raddr);
 
+struct smb_direct_connection *smb_direct_connection_create(TALLOC_CTX *mem_ctx);
 struct tevent_req *smb_direct_connection_connect_send(TALLOC_CTX *mem_ctx,
                                                      struct tevent_context *ev,
                                                      struct smb_direct_connection *c,
-                                                     const struct sockaddr_storage *src,
-                                                     const struct sockaddr_storage *dst);
+                                                     const struct sockaddr_storage *laddr,
+                                                     const struct sockaddr_storage *raddr);
 NTSTATUS smb_direct_connection_connect_recv(struct tevent_req *req, int *fd);
 
 NTSTATUS smb_direct_connection_setup_events(struct smb_direct_connection *c,
@@ -54,7 +67,7 @@ NTSTATUS smb_direct_connection_setup_events(struct smb_direct_connection *c,
 uint32_t smb_direct_connection_max_fragmented_size(struct smb_direct_connection *c);
 uint32_t smb_direct_connection_max_read_write_size(struct smb_direct_connection *c);
 
-#define SMB_DIRECT_LISTEN_BACKLOG 100
+
 
 struct tevent_req *smb_direct_daemon_send(TALLOC_CTX *mem_ctx,
                                          struct tevent_context *ev);
index 9c325b0d8019e08db075f96b57ee932d9f4cf6a4..5f6b9827951ea46cc738153fcf5f01a060fb05fe 100644 (file)
@@ -412,6 +412,8 @@ struct tevent_req *smb_direct_daemon_send(TALLOC_CTX *mem_ctx,
         */
        state->listen_path = listen_path;
 
+#define SMB_DIRECT_LISTEN_BACKLOG 100
+
        ret = listen(state->listen_fd, SMB_DIRECT_LISTEN_BACKLOG);
        if (ret != 0) {
                DBG_ERR("listen failed [%s]\n", strerror(errno));
@@ -523,10 +525,7 @@ static NTSTATUS smbd_direct_daemon_ping(
        return NT_STATUS_OK;
 }
 
-static void rdma_cm_handler(struct tevent_context *ev,
-                           struct tevent_fd *fde,
-                           uint16_t flags,
-                           void *private_data);
+static void smbd_direct_daemon_listen_accept_done(struct tevent_req *subreq);
 
 static NTSTATUS smbd_direct_daemon_listen(
        struct smb_direct_daemon_conn *conn,
@@ -534,8 +533,10 @@ static NTSTATUS smbd_direct_daemon_listen(
        struct sdd_packet_listen_response *listen_response)
 {
        struct smb_direct_daemon_state *daemon_state = conn->daemon_state;
-       struct sockaddr_in inaddr;
-       int result;
+       struct sockaddr_storage bind_addr;
+       struct smb_direct_listener *l = NULL;
+       NTSTATUS status;
+       struct tevent_req *subreq = NULL;
 
        DBG_ERR("got listen request...\n");
 
@@ -544,63 +545,32 @@ static NTSTATUS smbd_direct_daemon_listen(
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       daemon_state->rdma.cm_channel = rdma_create_event_channel();
-       if (daemon_state->rdma.cm_channel == NULL) {
-               DBG_ERR("rdma_create_event_channel failed [%s]\n",
-                       strerror(errno));
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-
-       set_close_on_exec(daemon_state->rdma.cm_channel->fd);
-       set_blocking(daemon_state->rdma.cm_channel->fd, false);
-
-       daemon_state->rdma.context.d = daemon_state;
-#if RDMA_USER_CM_MAX_ABI_VERSION >= 2
-       result = rdma_create_id(daemon_state->rdma.cm_channel,
-                               &daemon_state->rdma.cm_id,
-                               &daemon_state->rdma.context,
-                               RDMA_PS_TCP);
-#else
-       result = rdma_create_id(daemon_state->rdma.cm_channel,
-                               &daemon_state->rdma.cm_id,
-                               &daemon_state->rdma.context);
-#endif
-       if (result != 0) {
-               DBG_ERR("rdma_create_id failed [%s]\n",
-                       strerror(errno));
-               goto fail;
-       }
+       ZERO_STRUCT(bind_addr);
 
-       daemon_state->rdma.cm_channel_fde = tevent_add_fd(
-               conn->ev,
-               conn,
-               daemon_state->rdma.cm_channel->fd,
-               TEVENT_FD_READ,
-               rdma_cm_handler,
-               daemon_state);
-       if (daemon_state->rdma.cm_channel_fde == NULL) {
-               DBG_ERR("tevent_add_fd failed\n");
-               goto fail;
+       status = smbd_direct_listener_setup(conn, &bind_addr, &l);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("smbd_direct_listener_setup() => %s\n",
+                       nt_errstr(status));
+               return status;
        }
 
-       ZERO_STRUCT(inaddr);
-       inaddr.sin_family = AF_INET;
-       inaddr.sin_port = htons(5445);
-       inaddr.sin_addr.s_addr = INADDR_ANY;
-
-       result = rdma_bind_addr(daemon_state->rdma.cm_id,
-                               (struct sockaddr *)&inaddr);
-       if (result != 0) {
-               DBG_ERR("rdma_bind_addr failed\n");
-               goto fail;
-       }
+       // TODO: create an socketpair() with shutdown(SHUT_RD) or a pipe()
+       // and pass it allong, we'll to sendmsg() from our side
+       // and pass the metadata and the connection fd to the calling
+       // process. If the other end closes we need to free the
+       // listener.
 
-       result = rdma_listen(daemon_state->rdma.cm_id,
-                            SMB_DIRECT_LISTEN_BACKLOG);
-       if (result != 0) {
-               DBG_ERR("rdma_bind_addr failed\n");
-               goto fail;
+       subreq = smb_direct_listener_accept_send(l, daemon_state->ev, l);
+       if (subreq == NULL) {
+               TALLOC_FREE(l);
+               status = NT_STATUS_NO_MEMORY;
+               DBG_ERR("smbd_direct_listener_setup() => %s\n",
+                       nt_errstr(status));
+               return status;
        }
+       tevent_req_set_callback(subreq,
+                               smbd_direct_daemon_listen_accept_done,
+                               conn);
 
        conn->listening = true;
 
@@ -611,13 +581,42 @@ static NTSTATUS smbd_direct_daemon_listen(
        DBG_ERR("SMB-D daemon started accepting SMB-D connections\n");
 
        return NT_STATUS_OK;
+}
 
-fail:
-       rdma_destroy_id(daemon_state->rdma.cm_id);
-       daemon_state->rdma.cm_id = NULL;
-       rdma_destroy_event_channel(daemon_state->rdma.cm_channel);
-       daemon_state->rdma.cm_channel = NULL;
-       return NT_STATUS_INTERNAL_ERROR;
+static void smbd_direct_daemon_listen_accept_done(struct tevent_req *subreq)
+{
+       struct smb_direct_daemon_conn *conn = tevent_req_callback_data(subreq,
+                       struct smb_direct_daemon_conn);
+       struct smb_direct_daemon_state *daemon_state = conn->daemon_state;
+       struct smb_direct_connection *c = NULL;
+       int fd = -1;
+       struct sockaddr_storage laddr;
+       struct sockaddr_storage raddr;
+       NTSTATUS status;
+
+       ZERO_STRUCT(laddr);
+       ZERO_STRUCT(raddr);
+
+       status = smb_direct_listener_accept_recv(subreq, daemon_state,
+                                                &c, &fd, &laddr, &raddr);
+       /* no TALLOC_FREE(subreq)! we want to get more connections */
+       if (!NT_STATUS_IS_OK(status)) {
+               //TODO...
+               return;
+       }
+       subreq = NULL;
+
+       status = smb_direct_connection_setup_events(c, daemon_state->ev);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(c);
+               close(fd);
+               //TODO...
+               return;
+       }
+
+       //TODO: pass the caller
+       TALLOC_FREE(c);
+       close(fd);
 }
 
 static NTSTATUS smbd_direct_daemon_dispatch(struct smb_direct_daemon_conn *conn,
@@ -848,116 +847,4 @@ static int smb_direct_daemon_conn_recv(struct tevent_req *req)
        return tevent_req_simple_recv_unix(req);
 }
 
-static void rdma_cm_handler(struct tevent_context *ev,
-                           struct tevent_fd *fde,
-                           uint16_t flags,
-                           void *private_data)
-{
-       struct smb_direct_daemon_state *daemon_state = talloc_get_type_abort(
-               private_data, struct smb_direct_daemon_state);
-       struct smb_direct_connection *sconn = NULL;
-       struct rdma_cm_event *cm_ev = NULL;
-       int result;
-       NTSTATUS status;
-
-       DBG_ERR("SMB-D got connection event\n");
-
-       result = rdma_get_cm_event(daemon_state->rdma.cm_channel, &cm_ev);
-       if (result != 0) {
-               DBG_ERR("rdma_get_cm_event failed [%s]\n", strerror(errno));
-               return;
-       }
-
-       DBG_ERR("cm_event type [%d] cm_id [%p]\n",
-                 cm_ev->event, cm_ev->id);
-
-       switch (cm_ev->event) {
-       case RDMA_CM_EVENT_CONNECT_REQUEST: {
-               struct rdma_conn_param conn_param;
-               uint8_t ird_ord_hdr[8];
-
-               RSIVAL(ird_ord_hdr, 0, 0);
-               RSIVAL(ird_ord_hdr, 4, 16);
-
-               DBG_DEBUG("RDMA_CM_EVENT_CONNECT_REQUEST\n");
-
-               ZERO_STRUCT(conn_param);
-//             conn_param.private_data = ird_ord_hdr;
-//             conn_param.private_data_len = sizeof(ird_ord_hdr);
-               conn_param.responder_resources = 1;
-               conn_param.initiator_depth = 1;
-//             conn_param.retry_count = 10;
-
-               sconn = smb_direct_connection_listener(daemon_state,
-                                                      cm_ev->id);
-               if (sconn == NULL) {
-                       DBG_ERR("smb_direct_connection_create failed\n");
-                       goto fail;
-               }
-
-               status = smb_direct_connection_complete_alloc(sconn);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DBG_ERR("smb_direct_connection_complete_alloc failed\n");
-                       goto fail;
-               }
-
-               cm_ev->id->context = sconn;
-
-               result = rdma_accept(cm_ev->id, NULL);
-               if (result != 0) {
-                       DBG_ERR("rdma_accept failed [%s] result [%d]\n", strerror(errno), result);
-                       goto fail;
-               }
-
-               break;
-       }
-
-       case RDMA_CM_EVENT_ESTABLISHED:
-               DBG_DEBUG("RDMA_CM_EVENT_ESTABLISHED\n");
-
-               sconn = talloc_get_type_abort(cm_ev->id->context,
-                                             struct smb_direct_connection);
-               /*
-                * TODO: get things going...
-                */
-               break;
-
-       case RDMA_CM_EVENT_DISCONNECTED:
-               DBG_DEBUG("RDMA_CM_EVENT_DISCONNECTED\n");
-
-               sconn = talloc_get_type(cm_ev->id->context,
-                                       struct smb_direct_connection);
-               TALLOC_FREE(sconn);
-               break;
-
-       case RDMA_CM_EVENT_DEVICE_REMOVAL:
-               DBG_ERR("RDMA device removal\n");
-               goto fail;
-
-       default:
-               DBG_ERR("event %d\n", cm_ev->event);
-               goto fail;
-       }
-
-       result = rdma_ack_cm_event(cm_ev);
-       if (result != 0) {
-               DBG_ERR("rdma_ack_cm_event failed [%s]\n", strerror(errno));
-               goto fail;
-       }
-
-       return;
-
-fail:
-       rdma_ack_cm_event(cm_ev);
-
-       if (cm_ev->id == daemon_state->rdma.cm_id) {
-               /* Listening conn is erroring out, shut it down and die */
-               TALLOC_FREE(daemon_state->listening_conn);
-               // tevent_req_error(daemon_state->req, EPANIC);
-       }
-
-       TALLOC_FREE(sconn);
-       return;
-}
-
 #endif /* SMB_TRANSPORT_ENABLE_RDMA */