Skip to content

Commit

Permalink
nvmet: don't return "any" ip address in discovery log page
Browse files Browse the repository at this point in the history
Its perfectly valid to assign a nvmet port to listen on "any"
IP address (traddr 0.0.0.0 for ipv4 address family) for IP based
transport ports. However, we must not return this address in
discovery log entries. Instead we need to return the address
where the request was accepted on (req->port address).

Since this is nvme transport specific, introduce an optional
.disc_traddr interface that is designed to check that a
port in question is bound to "any" IP address and if so, set
the traddr from the port where the request came from.

Reviewed-by: Johannes Thumshirn <[email protected]>
Signed-off-by: Sagi Grimberg <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
sagigrimberg authored and axboe committed Mar 26, 2018
1 parent a470143 commit 4c65268
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
30 changes: 27 additions & 3 deletions drivers/nvme/target/discovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ void nvmet_referral_disable(struct nvmet_port *port)
}

static void nvmet_format_discovery_entry(struct nvmf_disc_rsp_page_hdr *hdr,
struct nvmet_port *port, char *subsys_nqn, u8 type, u32 numrec)
struct nvmet_port *port, char *subsys_nqn, char *traddr,
u8 type, u32 numrec)
{
struct nvmf_disc_rsp_page_entry *e = &hdr->entries[numrec];

Expand All @@ -56,11 +57,30 @@ static void nvmet_format_discovery_entry(struct nvmf_disc_rsp_page_hdr *hdr,
e->asqsz = cpu_to_le16(NVME_AQ_DEPTH);
e->subtype = type;
memcpy(e->trsvcid, port->disc_addr.trsvcid, NVMF_TRSVCID_SIZE);
memcpy(e->traddr, port->disc_addr.traddr, NVMF_TRADDR_SIZE);
memcpy(e->traddr, traddr, NVMF_TRADDR_SIZE);
memcpy(e->tsas.common, port->disc_addr.tsas.common, NVMF_TSAS_SIZE);
memcpy(e->subnqn, subsys_nqn, NVMF_NQN_SIZE);
}

/*
* nvmet_set_disc_traddr - set a correct discovery log entry traddr
*
* IP based transports (e.g RDMA) can listen on "any" ipv4/ipv6 addresses
* (INADDR_ANY or IN6ADDR_ANY_INIT). The discovery log page traddr reply
* must not contain that "any" IP address. If the transport implements
* .disc_traddr, use it. this callback will set the discovery traddr
* from the req->port address in case the port in question listens
* "any" IP address.
*/
static void nvmet_set_disc_traddr(struct nvmet_req *req, struct nvmet_port *port,
char *traddr)
{
if (req->ops->disc_traddr)
req->ops->disc_traddr(req, port, traddr);
else
memcpy(traddr, port->disc_addr.traddr, NVMF_TRADDR_SIZE);
}

static void nvmet_execute_get_disc_log_page(struct nvmet_req *req)
{
const int entry_size = sizeof(struct nvmf_disc_rsp_page_entry);
Expand Down Expand Up @@ -90,8 +110,11 @@ static void nvmet_execute_get_disc_log_page(struct nvmet_req *req)
if (!nvmet_host_allowed(req, p->subsys, ctrl->hostnqn))
continue;
if (residual_len >= entry_size) {
char traddr[NVMF_TRADDR_SIZE];

nvmet_set_disc_traddr(req, req->port, traddr);
nvmet_format_discovery_entry(hdr, req->port,
p->subsys->subsysnqn,
p->subsys->subsysnqn, traddr,
NVME_NQN_NVME, numrec);
residual_len -= entry_size;
}
Expand All @@ -102,6 +125,7 @@ static void nvmet_execute_get_disc_log_page(struct nvmet_req *req)
if (residual_len >= entry_size) {
nvmet_format_discovery_entry(hdr, r,
NVME_DISC_SUBSYS_NAME,
r->disc_addr.traddr,
NVME_NQN_DISC, numrec);
residual_len -= entry_size;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/nvme/target/nvmet.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ struct nvmet_fabrics_ops {
int (*add_port)(struct nvmet_port *port);
void (*remove_port)(struct nvmet_port *port);
void (*delete_ctrl)(struct nvmet_ctrl *ctrl);
void (*disc_traddr)(struct nvmet_req *req,
struct nvmet_port *port, char *traddr);
};

#define NVMET_MAX_INLINE_BIOVEC 8
Expand Down
18 changes: 18 additions & 0 deletions drivers/nvme/target/rdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,23 @@ static void nvmet_rdma_remove_port(struct nvmet_port *port)
rdma_destroy_id(cm_id);
}

static void nvmet_rdma_disc_port_addr(struct nvmet_req *req,
struct nvmet_port *port, char *traddr)
{
struct rdma_cm_id *cm_id = port->priv;

if (inet_addr_is_any((struct sockaddr *)&cm_id->route.addr.src_addr)) {
struct nvmet_rdma_rsp *rsp =
container_of(req, struct nvmet_rdma_rsp, req);
struct rdma_cm_id *req_cm_id = rsp->queue->cm_id;
struct sockaddr *addr = (void *)&req_cm_id->route.addr.src_addr;

sprintf(traddr, "%pISc", addr);
} else {
memcpy(traddr, port->disc_addr.traddr, NVMF_TRADDR_SIZE);
}
}

static struct nvmet_fabrics_ops nvmet_rdma_ops = {
.owner = THIS_MODULE,
.type = NVMF_TRTYPE_RDMA,
Expand All @@ -1455,6 +1472,7 @@ static struct nvmet_fabrics_ops nvmet_rdma_ops = {
.remove_port = nvmet_rdma_remove_port,
.queue_response = nvmet_rdma_queue_response,
.delete_ctrl = nvmet_rdma_delete_ctrl,
.disc_traddr = nvmet_rdma_disc_port_addr,
};

static void nvmet_rdma_remove_one(struct ib_device *ib_device, void *client_data)
Expand Down

0 comments on commit 4c65268

Please sign in to comment.