acme can display end-point information. This is implemented in acm by iterating through all end-points and their ports, until the end-point indexes match. This implies, considering a multi-ported device, that the address information associated with the first port is the only one displayed. Before this commit: # ibstat | grep ports Number of ports: 2 # ib_acme -e svc,guid,port,pkey,ep_index,prov,addr_0,addresses ibacm-unix.sock,0x0021280001a17c96,1,0xffff,1,ibacmp,lab36,lab36-1,192.168.2.2 Fixed by adding port_num to the equation, and the above command will yield: # ib_acme -e svc,guid,port,pkey,ep_index,prov,addr_0,addresses ibacm-unix.sock,0x0021280001a17c96,1,0xffff,1,ibacmp,192.168.2.2,lab36,lab36-1 ibacm-unix.sock,0x0021280001a17c96,2,0xffff,1,ibacmp,192.168.2.3,lab36-2 Signed-off-by: Håkon Bugge <haakon.bugge@xxxxxxxxxx> --- v1 -> v2: * Incorporated review comments from Doug * Fixed a memory leak in enumerate_ep() introduced by v1 * Hardened enumerate_ep() related to the first EP being unavailable --- ibacm/include/infiniband/acm.h | 6 ++-- ibacm/src/acm.c | 11 +++++-- ibacm/src/acme.c | 36 ++++++++++++++--------- ibacm/src/libacm.c | 53 +++++++++++++++++++++++----------- ibacm/src/libacm.h | 2 +- 5 files changed, 71 insertions(+), 37 deletions(-) diff --git a/ibacm/include/infiniband/acm.h b/ibacm/include/infiniband/acm.h index f6efee18..90f3d431 100644 --- a/ibacm/include/infiniband/acm.h +++ b/ibacm/include/infiniband/acm.h @@ -73,7 +73,8 @@ struct acm_hdr { uint8_t version; uint8_t opcode; uint8_t status; - uint8_t data[3]; + uint8_t port_num; + uint8_t data[2]; uint16_t length; uint64_t tid; }; @@ -135,7 +136,8 @@ struct acm_perf_msg { struct acm_ep_config_data { uint64_t dev_guid; uint8_t port_num; - uint8_t rsvd[3]; + uint8_t phys_port_cnt; + uint8_t rsvd[2]; uint16_t pkey; uint16_t addr_cnt; uint8_t prov_name[ACM_MAX_PROV_NAME]; diff --git a/ibacm/src/acm.c b/ibacm/src/acm.c index 6453c5f0..8f25f34b 100644 --- a/ibacm/src/acm.c +++ b/ibacm/src/acm.c @@ -876,7 +876,9 @@ static struct acmc_addr *acm_get_ep_address(struct acm_ep_addr_data *data) return NULL; } -static struct acmc_ep *acm_get_ep(int index) +/* If port_num is zero, iterate through all ports, otherwise consider + * only the specific port_num */ +static struct acmc_ep *acm_get_ep(int index, uint8_t port_num) { struct acmc_device *dev; struct acmc_ep *ep; @@ -885,6 +887,8 @@ static struct acmc_ep *acm_get_ep(int index) acm_log(2, "ep index %d\n", index); list_for_each(&dev_list, dev, entry) { for (i = 0; i < dev->port_cnt; i++) { + if (port_num && port_num != (i + 1)) + continue; if (dev->port[i].state != IBV_PORT_ACTIVE) continue; list_for_each(&dev->port[i].ep_list, ep, entry) { @@ -1156,7 +1160,7 @@ static int acm_svr_perf_query(struct acmc_client *client, struct acm_msg *msg) len = ACM_MSG_HDR_LENGTH + (ACM_MAX_COUNTER * sizeof(uint64_t)); } else { if (index >= 1) { - ep = acm_get_ep(index - 1); + ep = acm_get_ep(index - 1, msg->hdr.port_num); } else { addr = acm_get_ep_address(&msg->resolve_data[0]); if (addr) @@ -1193,11 +1197,12 @@ static int acm_svr_ep_query(struct acmc_client *client, struct acm_msg *msg) acm_log(2, "client %d\n", client->index); index = msg->hdr.data[0]; - ep = acm_get_ep(index - 1); + ep = acm_get_ep(index - 1, msg->hdr.port_num); if (ep) { msg->hdr.status = ACM_STATUS_SUCCESS; msg->ep_data[0].dev_guid = ep->port->dev->device.dev_guid; msg->ep_data[0].port_num = ep->port->port.port_num; + msg->ep_data[0].phys_port_cnt = ep->port->dev->port_cnt; msg->ep_data[0].pkey = htobe16(ep->endpoint.pkey); strncpy((char *)msg->ep_data[0].prov_name, ep->port->prov->name, ACM_MAX_PROV_NAME - 1); diff --git a/ibacm/src/acme.c b/ibacm/src/acme.c index b592b977..1289fa36 100644 --- a/ibacm/src/acme.c +++ b/ibacm/src/acme.c @@ -926,24 +926,32 @@ static int enumerate_ep(char *svc, int index) static int labels; int ret, i; struct acm_ep_config_data *ep_data; + int phys_port_cnt = 255; + int found = 0; + int port; - ret = ib_acm_enum_ep(index, &ep_data); - if (ret) - return ret; + for (port = 1; port <= phys_port_cnt; ++port) { + ret = ib_acm_enum_ep(index, &ep_data, port); + if (ret) + continue; - if (!labels) { - printf("svc,guid,port,pkey,ep_index,prov,addr_0,addresses\n"); - labels = 1; - } + found = 1; - printf("%s,0x%016" PRIx64 ",%d,0x%04x,%d,%s", svc, ep_data->dev_guid, - ep_data->port_num, ep_data->pkey, index, ep_data->prov_name); - for (i = 0; i < ep_data->addr_cnt; i++) - printf(",%s", ep_data->addrs[i].name); - printf("\n"); - ib_acm_free_ep_data(ep_data); + if (!labels) { + printf("svc,guid,port,pkey,ep_index,prov,addr_0,addresses\n"); + labels = 1; + } - return 0; + printf("%s,0x%016" PRIx64 ",%d,0x%04x,%d,%s", svc, ep_data->dev_guid, + ep_data->port_num, ep_data->pkey, index, ep_data->prov_name); + for (i = 0; i < ep_data->addr_cnt; i++) + printf(",%s", ep_data->addrs[i].name); + printf("\n"); + phys_port_cnt = ep_data->phys_port_cnt; + ib_acm_free_ep_data(ep_data); + } + + return !found; } static void enumerate_eps(char *svc) diff --git a/ibacm/src/libacm.c b/ibacm/src/libacm.c index 1d9d7145..92f5baf9 100644 --- a/ibacm/src/libacm.c +++ b/ibacm/src/libacm.c @@ -382,18 +382,21 @@ out: return ret; } -int ib_acm_enum_ep(int index, struct acm_ep_config_data **data) +int ib_acm_enum_ep(int index, struct acm_ep_config_data **data, uint8_t port) { + struct acm_ep_config_data *netw_edata = NULL; + struct acm_ep_config_data *host_edata = NULL; + struct acm_hdr hdr; struct acm_msg msg; int ret; int len; - int cnt; - struct acm_ep_config_data *edata; + int i; pthread_mutex_lock(&acm_lock); memset(&msg, 0, sizeof msg); msg.hdr.version = ACM_VERSION; msg.hdr.opcode = ACM_OP_EP_QUERY; + msg.hdr.port_num = port; msg.hdr.data[0] = index; msg.hdr.length = htobe16(ACM_MSG_HDR_LENGTH); @@ -401,33 +404,49 @@ int ib_acm_enum_ep(int index, struct acm_ep_config_data **data) if (ret != ACM_MSG_HDR_LENGTH) goto out; - ret = recv(sock, (char *) &msg, sizeof msg, 0); - if (ret < ACM_MSG_HDR_LENGTH || ret != be16toh(msg.hdr.length)) { + ret = recv(sock, (char *) &hdr, sizeof(hdr), 0); + if (ret != sizeof(hdr)) { ret = ACM_STATUS_EINVAL; goto out; } - if (msg.hdr.status) { - ret = acm_error(msg.hdr.status); + if (hdr.status) { + ret = acm_error(hdr.status); goto out; } - cnt = be16toh(msg.ep_data[0].addr_cnt); - len = sizeof(struct acm_ep_config_data) + - ACM_MAX_ADDRESS * cnt; - edata = malloc(len); - if (!edata) { + len = be16toh(hdr.length) - sizeof(hdr); + netw_edata = (struct acm_ep_config_data *)malloc(len); + host_edata = (struct acm_ep_config_data *)malloc(len); + if (!netw_edata || !host_edata) { ret = ACM_STATUS_ENOMEM; goto out; } - memcpy(edata, &msg.ep_data[0], len); - edata->dev_guid = be64toh(msg.ep_data[0].dev_guid); - edata->pkey = be16toh(msg.ep_data[0].pkey); - edata->addr_cnt = cnt; - *data = edata; + ret = recv(sock, (char *)netw_edata, len, 0); + if (ret != len) { + ret = ACM_STATUS_EINVAL; + goto out; + } + + host_edata->dev_guid = be64toh(netw_edata->dev_guid); + host_edata->port_num = netw_edata->port_num; + host_edata->phys_port_cnt = netw_edata->phys_port_cnt; + host_edata->pkey = be16toh(netw_edata->pkey); + host_edata->addr_cnt = be16toh(netw_edata->addr_cnt); + + memcpy(host_edata->prov_name, netw_edata->prov_name, + sizeof(host_edata->prov_name)); + + for (i = 0; i < host_edata->addr_cnt; ++i) + host_edata->addrs[i] = netw_edata->addrs[i]; + + *data = host_edata; ret = 0; out: + free(netw_edata); + if (ret) + free(host_edata); pthread_mutex_unlock(&acm_lock); return ret; } diff --git a/ibacm/src/libacm.h b/ibacm/src/libacm.h index bf8cb79b..fb81b417 100644 --- a/ibacm/src/libacm.h +++ b/ibacm/src/libacm.h @@ -54,7 +54,7 @@ int ib_acm_query_perf_ep_addr(uint8_t *src, uint8_t type, const char *ib_acm_cntr_name(int index); -int ib_acm_enum_ep(int index, struct acm_ep_config_data **data); +int ib_acm_enum_ep(int index, struct acm_ep_config_data **data, uint8_t port); #define ib_acm_free_ep_data(data) free(data) #endif /* LIBACM_H */ -- 2.19.2