@@ -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];
@@ -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);
@@ -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)
@@ -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;
}
@@ -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 */
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@oracle.com> --- 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(-)