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.max_read_write_size = 1048576;
c->state.receive_credit_max = 10;//255;
c->state.send_credit_target = 255;
c->state.keep_alive_internal = 5;
return tevent_req_post(req, ev);
}
- return NULL;
+ return req;
}
static void smb_direct_connection_negotiate_accept_rdma_handler(
}
switch (c->rdma.cm_event->event) {
+ case RDMA_CM_EVENT_ESTABLISHED:
+ DEBUG(0,("RDMA conn established [%p]\n", c));
+ rdma_ack_cm_event(c->rdma.cm_event);
+ c->rdma.cm_event = NULL;
+ return;
case RDMA_CM_EVENT_DISCONNECTED:
status = NT_STATUS_CONNECTION_DISCONNECTED;
DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
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_ADDR_CHANGE:
case RDMA_CM_EVENT_TIMEWAIT_EXIT:
status = NT_STATUS_INVALID_NETWORK_RESPONSE;
- DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
- __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
+ DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s] event [%d] "
+ "RDMA_CM_EVENT_REJECTED [%d]\n",
+ __location__, __FUNCTION__, ret, errno, nt_errstr(status),
+ c->rdma.cm_event->event, RDMA_CM_EVENT_REJECTED));
tevent_req_nterror(req, status);
return;
}
int ret;
uint16_t credits_requested;
uint16_t credits_granted;
- uint32_t max_read_write_size;
uint32_t preferred_send_size;
uint32_t max_receive_size;
uint32_t max_fragmented_size;
uint32_t tmp;
struct smb_direct_io *io = NULL;
+ struct smb_direct_io *neg_send = NULL;
+ struct ibv_send_wr *bad_send_wr = NULL;
DEBUG(0,("%s:%s: here...\n", __location__, __func__));
DEBUG(0,("%s:%s: GOT RECV[%p] next[%p] ret[%d] errno[%d]\n",
__location__, __FUNCTION__, io, io->recv_wr.next, ret, errno));
//dump_data(0, io->data, wc.byte_len);
- if (wc.byte_len < 0x20) {
+ if (wc.byte_len < 0x14) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE;
DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
__location__, __FUNCTION__, ret, errno, nt_errstr(status)));
tevent_req_nterror(req, status);
return;
}
- if (SVAL(io->data, 0x04) != 0x0100) {
- status = NT_STATUS_INVALID_NETWORK_RESPONSE;
- DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
- __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
- tevent_req_nterror(req, status);
- return;
- }
- credits_requested = SVAL(io->data, 0x08);
+
+ credits_requested = SVAL(io->data, 0x06);
if (credits_requested == 0) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE;
DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
tevent_req_nterror(req, status);
return;
}
- credits_granted = SVAL(io->data, 0x0A);
- if (credits_granted == 0) {
- status = NT_STATUS_INVALID_NETWORK_RESPONSE;
- DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
- __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
- tevent_req_nterror(req, status);
- return;
- }
- status = NT_STATUS(IVAL(io->data, 0x0C));
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
- __location__, __FUNCTION__, ret, errno, nt_errstr(status)));
- tevent_req_nterror(req, status);
- return;
- }
- max_read_write_size = IVAL(io->data, 0x10);
- preferred_send_size = IVAL(io->data, 0x14);
+
+ preferred_send_size = IVAL(io->data, 0x08);
if (preferred_send_size > c->state.max_receive_size) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE;
DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
tevent_req_nterror(req, status);
return;
}
- max_receive_size = IVAL(io->data, 0x18);
+
+ max_receive_size = IVAL(io->data, 0x0c);
if (max_receive_size < 0x80) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE;
DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
tevent_req_nterror(req, status);
return;
}
- max_fragmented_size = IVAL(io->data, 0x1C);
+
+ max_fragmented_size = IVAL(io->data, 0x10);
if (max_fragmented_size < 0x20000) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE;
DEBUG(0,("%s:%s: ret[%d] errno[%d] status[%s]\n",
return;
}
+ credits_granted = 1;
+
c->state.receive_credit_target = credits_requested;
tmp = c->state.max_receive_size;
tmp = MIN(tmp, max_receive_size);
c->state.max_send_size = tmp;
- tmp = MIN(1048576, max_read_write_size);
- c->state.max_read_write_size = tmp;
-
- tmp = c->state.max_fragmented_size;
- tmp = MIN(tmp, max_fragmented_size);
- c->state.max_fragmented_size = tmp;
-
c->state.send_credits = credits_granted;
TALLOC_FREE(c->ibv.fde_channel);
DEBUG(0,("%s:%s: ret[%d] errno[%d]\n",
__location__, __FUNCTION__, ret, errno));
+ smb_direct_connection_debug_credits(c, __location__, __FUNCTION__);
+
TALLOC_FREE(io);
errno = 0;
return;
}
+ neg_send = c->s2r.idle;
+ DLIST_REMOVE(c->s2r.idle, neg_send);
+
+ SSVAL(neg_send->data, 0x00, 0x0100);
+ SSVAL(neg_send->data, 0x02, 0x0100);
+ SSVAL(neg_send->data, 0x04, 0x0100);
+ SSVAL(neg_send->data, 0x06, 0x0000);
+
+ credits_granted = c->state.receive_credit_max;
+ credits_granted -= c->state.receive_credits;
+ credits_granted = MIN(credits_granted, c->state.receive_credit_target);
+
+ SSVAL(neg_send->data, 0x08, c->state.send_credit_target);
+ SSVAL(neg_send->data, 0x0a, credits_granted);
+ SIVAL(neg_send->data, 0x0c, NT_STATUS_V(NT_STATUS_OK));
+ SIVAL(neg_send->data, 0x10, c->state.max_read_write_size);
+ SIVAL(neg_send->data, 0x14, c->state.max_send_size);
+ SIVAL(neg_send->data, 0x18, c->state.max_receive_size);
+ SIVAL(neg_send->data, 0x1c, c->state.max_fragmented_size);
+
+ neg_send->sge[0].addr = (uint64_t) (uintptr_t) neg_send->data;
+ neg_send->sge[0].length = 0x20;
+ neg_send->sge[0].lkey = neg_send->data_mr->lkey;
+ neg_send->send_wr.opcode = IBV_WR_SEND;
+ neg_send->send_wr.send_flags = IBV_SEND_SIGNALED;
+ neg_send->send_wr.sg_list = neg_send->sge;
+ neg_send->send_wr.num_sge = 1;
+
+ ret = ibv_post_send(c->ibv.qp, &neg_send->send_wr, &bad_send_wr);
+ 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)));
+ tevent_req_nterror(req, status);
+ return;
+ }
tevent_req_done(req);
return;