nvme/rdma: add option to specify source address

Allow the user to set the source address when connecting to a NVMe-oF
controller.

Change-Id: Ice3add4b2cd3b64fdb8d0d7807d2235f90fd86b1
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/375837
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Daniel Verkamp 2017-08-25 15:05:01 -07:00
parent 63af5ff13b
commit 6847a679ea
3 changed files with 40 additions and 7 deletions

View File

@ -116,6 +116,20 @@ struct spdk_nvme_ctrlr_opts {
* or driver-assisted striping.
*/
uint32_t io_queue_requests;
/**
* Source address for NVMe-oF connections.
* Set src_addr and src_svcid to empty strings if no source address should be
* specified.
*/
char src_addr[SPDK_NVMF_TRADDR_MAX_LEN + 1];
/**
* Source service ID (port) for NVMe-oF connections.
* Set src_addr and src_svcid to empty strings if no source address should be
* specified.
*/
char src_svcid[SPDK_NVMF_TRSVCID_MAX_LEN + 1];
};
/**

View File

@ -85,6 +85,8 @@ spdk_nvme_ctrlr_opts_set_defaults(struct spdk_nvme_ctrlr_opts *opts)
opts->io_queue_size = DEFAULT_IO_QUEUE_SIZE;
strncpy(opts->hostnqn, DEFAULT_HOSTNQN, sizeof(opts->hostnqn));
opts->io_queue_requests = DEFAULT_IO_QUEUE_REQUESTS;
memset(opts->src_addr, 0, sizeof(opts->src_addr));
memset(opts->src_svcid, 0, sizeof(opts->src_svcid));
}
/**

View File

@ -432,13 +432,14 @@ nvme_rdma_recv(struct nvme_rdma_qpair *rqpair, uint64_t rsp_idx)
static int
nvme_rdma_resolve_addr(struct nvme_rdma_qpair *rqpair,
struct sockaddr_storage *sin,
struct sockaddr *src_addr,
struct sockaddr *dst_addr,
struct rdma_event_channel *cm_channel)
{
int ret;
struct rdma_cm_event *event;
ret = rdma_resolve_addr(rqpair->cm_id, NULL, (struct sockaddr *) sin,
ret = rdma_resolve_addr(rqpair->cm_id, src_addr, dst_addr,
NVME_RDMA_TIME_OUT_IN_MS);
if (ret) {
SPDK_ERRLOG("rdma_resolve_addr, %d\n", errno);
@ -699,7 +700,9 @@ nvme_rdma_unregister_mem(struct nvme_rdma_qpair *rqpair)
static int
nvme_rdma_qpair_connect(struct nvme_rdma_qpair *rqpair)
{
struct sockaddr_storage sin;
struct sockaddr_storage dst_addr;
struct sockaddr_storage src_addr;
bool src_addr_specified;
int rc;
struct spdk_nvme_ctrlr *ctrlr;
int family;
@ -726,22 +729,36 @@ nvme_rdma_qpair_connect(struct nvme_rdma_qpair *rqpair)
SPDK_DEBUGLOG(SPDK_TRACE_NVME, "adrfam %d ai_family %d\n", ctrlr->trid.adrfam, family);
memset(&sin, 0, sizeof(struct sockaddr_storage));
memset(&dst_addr, 0, sizeof(dst_addr));
SPDK_DEBUGLOG(SPDK_TRACE_NVME, "trsvcid is %s\n", ctrlr->trid.trsvcid);
rc = nvme_rdma_parse_addr(&sin, family, ctrlr->trid.traddr, ctrlr->trid.trsvcid);
rc = nvme_rdma_parse_addr(&dst_addr, family, ctrlr->trid.traddr, ctrlr->trid.trsvcid);
if (rc != 0) {
SPDK_ERRLOG("nvme_rdma_parse_addr() failed\n");
SPDK_ERRLOG("dst_addr nvme_rdma_parse_addr() failed\n");
return -1;
}
if (ctrlr->opts.src_addr[0] || ctrlr->opts.src_svcid[0]) {
memset(&src_addr, 0, sizeof(src_addr));
rc = nvme_rdma_parse_addr(&src_addr, family, ctrlr->opts.src_addr, ctrlr->opts.src_svcid);
if (rc != 0) {
SPDK_ERRLOG("src_addr nvme_rdma_parse_addr() failed\n");
return -1;
}
src_addr_specified = true;
} else {
src_addr_specified = false;
}
rc = rdma_create_id(rqpair->cm_channel, &rqpair->cm_id, rqpair, RDMA_PS_TCP);
if (rc < 0) {
SPDK_ERRLOG("rdma_create_id() failed\n");
return -1;
}
rc = nvme_rdma_resolve_addr(rqpair, &sin, rqpair->cm_channel);
rc = nvme_rdma_resolve_addr(rqpair,
src_addr_specified ? (struct sockaddr *)&src_addr : NULL,
(struct sockaddr *)&dst_addr, rqpair->cm_channel);
if (rc < 0) {
SPDK_ERRLOG("nvme_rdma_resolve_addr() failed\n");
return -1;