--- /dev/null
+Bottom: 590da5d69e0758287825bf4e7f25cfd32e149041
+Top: 3ca44cb6f244a91dc40f2675d2828ce532d4d24f
+Author: Sean Hefty <sean.hefty@intel.com>
+Date: 2011-06-28 16:43:46 -0700
+
+Refresh of counters
+
+---
+
+diff --git a/include/infiniband/acm.h b/include/infiniband/acm.h
+index 7f55b47..20d1b9e 100644
+--- a/include/infiniband/acm.h
++++ b/include/infiniband/acm.h
+@@ -67,7 +67,7 @@ struct acm_hdr {
+ uint8_t version;
+ uint8_t opcode;
+ uint8_t status;
+- uint8_t reserved[3];
++ uint8_t data[3];
+ uint16_t length;
+ uint64_t tid;
+ };
+@@ -98,6 +98,16 @@ struct acm_resolve_msg {
+ struct acm_ep_addr_data data[0];
+ };
+
++enum {
++ ACM_CNTR_ERROR,
++ ACM_CNTR_RESOLVE,
++ ACM_CNTR_ADDR_CACHE,
++ ACM_CNTR_ADDR_QUERY,
++ ACM_CNTR_ROUTE_CACHE,
++ ACM_CNTR_ROUTE_QUERY,
++ ACM_MAX_COUNTER
++};
++
+ struct acm_perf_msg {
+ struct acm_hdr hdr;
+ uint64_t data[0];
+diff --git a/man/ib_acm.1 b/man/ib_acm.1
+index acf6a1d..af57d0b 100644
+--- a/man/ib_acm.1
++++ b/man/ib_acm.1
+@@ -38,7 +38,7 @@ These steps assume that the user has administrative privileges.
+ .P
+ 2. Install the IB ACM package. This installs ib_acm, and ib_acme.
+ .P
+-3. Run 'ib_acm -D' as administrator to start the ib_acm daemon.
++3. Run 'ib_acm' as administrator to start the ib_acm daemon.
+ .P
+ 4. Optionally, run 'ib_acme -d <dest_ip> -v' to verify that
+ the ib_acm service is running.
+diff --git a/src/acm.c b/src/acm.c
+index 679af44..c4b60e8 100644
+--- a/src/acm.c
++++ b/src/acm.c
+@@ -47,7 +47,7 @@
+ #include <search.h>
+ #include "acm_mad.h"
+
+-#define src_out reserved[0]
++#define src_out data[0]
+
+ #define MAX_EP_ADDR 4
+ #define MAX_EP_MC 2
+@@ -60,16 +60,6 @@ enum acm_state {
+ ACM_READY
+ };
+
+-enum {
+- ACM_CNTR_ERROR,
+- ACM_CNTR_RESOLVE,
+- ACM_CNTR_ADDR_CACHE,
+- ACM_CNTR_ADDR_QUERY,
+- ACM_CNTR_ROUTE_CACHE,
+- ACM_CNTR_ROUTE_QUERY,
+- ACM_MAX_COUNTER
+-};
+-
+ enum acm_addr_prot {
+ ACM_ADDR_PROT_ACM
+ };
+@@ -1030,7 +1020,7 @@ acm_client_resolve_resp(struct acm_client *client, struct acm_resolve_msg *req_m
+ resp_msg->hdr.opcode |= ACM_OP_ACK;
+ resp_msg->hdr.status = status;
+ resp_msg->hdr.length = ACM_MSG_HDR_LENGTH;
+- memset(resp_msg->hdr.reserved, 0, sizeof(resp_msg->hdr.reserved));
++ memset(resp_msg->hdr.data, 0, sizeof(resp_msg->hdr.data));
+
+ if (status == ACM_STATUS_SUCCESS) {
+ resp_msg->hdr.length += ACM_MSG_EP_LENGTH;
+@@ -2244,8 +2234,25 @@ static int acm_svr_resolve(struct acm_client *client, struct acm_resolve_msg *ms
+
+ static int acm_svr_perf_query(struct acm_client *client, struct acm_perf_msg *msg)
+ {
+- /* TODO: return perf counters */
+- return 0;
++ int i;
++
++ acm_log(2, "client %d\n", client->index);
++ msg->hdr.opcode |= ACM_OP_ACK;
++ msg->hdr.status = ACM_STATUS_SUCCESS;
++ msg->hdr.data[0] = ACM_MAX_COUNTER;
++ msg->hdr.data[1] = 0;
++ msg->hdr.data[2] = 0;
++ msg->hdr.length = ACM_MSG_HDR_LENGTH + (ACM_MAX_COUNTER * sizeof(uint64_t));
++
++ for (i = 0; i < ACM_MAX_COUNTER; i++)
++ msg->data[i] = atomic_get(&counter[i]);
++
++ ret = send(client->sock, (char *) msg, msg->hdr.length, 0);
++ if (ret != msg->hdr.length)
++ acm_log(0, "ERROR - failed to send response\n");
++ else
++ ret = 0
++ return ret;
+ }
+
+ static void acm_svr_receive(struct acm_client *client)
+diff --git a/src/acme.c b/src/acme.c
+index d42ba81..bc51faa 100644
+--- a/src/acme.c
++++ b/src/acme.c
+@@ -52,8 +52,6 @@ static char *src_addr;
+ static char addr_type = 'u';
+ static int verify;
+ static int nodelay;
+-static int make_addr;
+-static int make_opts;
+ int verbose;
+
+ struct ibv_context **verbs;
+@@ -74,6 +72,8 @@ static void show_usage(char *program)
+ printf(" [-v] - verify ACM response against SA query response\n");
+ printf(" [-c] - read ACM cached data only\n");
+ printf("usage 2: %s\n", program);
++ printf(" -P dest_addr - query performance data from destination service");
++ printf("usage 3: %s\n", program);
+ printf(" -A [addr_file] - generate local address configuration file\n");
+ printf(" (default is %s)\n", ACM_ADDR_FILE);
+ printf(" -O [opt_file] - generate local acm_opts.cfg options file\n");
+@@ -583,11 +583,9 @@ static char *get_dest(char *arg, char *format)
+ static int resolve(char *program, char *dest_arg)
+ {
+ char **dest_list;
+- struct ibv_path_record path;
+ int ret, i = 0;
+- char dest_type;
+
+- ret = libacm_init();
++ ret = ib_acm_connect("127.0.0.1");
+ if (ret) {
+ printf("Unable to contact ib_acm service\n");
+ return ret;
+@@ -631,7 +629,47 @@ static int resolve(char *program, char *dest_arg)
+ }
+
+ free(dest_list);
+- libacm_cleanup();
++ ib_acm_disconnect();
++ return ret;
++}
++
++static int perf_query(char *program, char *dest_arg)
++{
++ char **dest_list;
++ int ret, cnt, i, d = 0;
++ uint64_t *counters;
++
++ dest_list = parse(dest_arg, NULL);
++ if (!dest_list) {
++ printf("Unable to parse destination argument\n");
++ return -1;
++ }
++
++ printf("Destination,Error Count,Resolve Count,Addr Cache Count,"
++ "Addr Query Count,Route Cache Count,Route Query Count\n")
++ for (dest_addr = get_dest(dest_list[d], &dest_type); dest_addr;
++ dest_addr = get_dest(dest_list[++d], &dest_type)) {
++
++ printf("%s,", dest_addr);
++ ret = ib_acm_connect(dest_addr);
++ if (ret) {
++ printf("Unable to contact ib_acm service\n);
++ continue;
++ }
++
++ ret = ib_acm_query_perf(&counters, &cnt);
++ if (ret) {
++ printf("Failed to query perf data %s\n", strerror(errno));
++ } else {
++ for (i = 0; i < cnt; i++)
++ printf("%ull,", counters[i]);
++ printf("\n");
++ }
++
++ ib_acm_disconnect();
++ }
++
++ free(dest_list);
+ return ret;
+ }
+
+@@ -650,12 +688,15 @@ int CDECL_FUNC main(int argc, char **argv)
+ {
+ char *dest_arg = NULL;
+ int op, ret;
++ int make_addr = 0;
++ int make_opts = 0;
++ int perf_query = 0;
+
+ ret = osd_init();
+ if (ret)
+ goto out;
+
+- while ((op = getopt(argc, argv, "f:s:d:vcA::O::D:V")) != -1) {
++ while ((op = getopt(argc, argv, "f:s:d:vcA::O::D:P:V")) != -1) {
+ switch (op) {
+ case 'f':
+ addr_type = optarg[0];
+@@ -685,6 +726,9 @@ int CDECL_FUNC main(int argc, char **argv)
+ case 'D':
+ dest_dir = optarg;
+ break;
++ case 'P':
++ dest_arg = optarg;
++ break;
+ case 'V':
+ verbose = 1;
+ break;
+@@ -700,8 +744,12 @@ int CDECL_FUNC main(int argc, char **argv)
+ exit(1);
+ }
+
+- if (dest_arg)
+- ret = resolve(argv[0], dest_arg);
++ if (dest_arg) {
++ if (perf_query)
++ ret = perf_query(argv[0], dest_arg);
++ else
++ ret = resolve(argv[0], dest_arg);
++ }
+
+ if (!ret && make_addr)
+ ret = gen_addr();
+@@ -709,6 +757,7 @@ int CDECL_FUNC main(int argc, char **argv)
+ if (!ret && make_opts)
+ ret = gen_opts();
+
++ osd_close();
+ out:
+ if (verbose || !(make_addr || make_opts) || ret)
+ printf("return status 0x%x\n", ret);
+diff --git a/src/libacm.c b/src/libacm.c
+index 31014d1..4491506 100644
+--- a/src/libacm.c
++++ b/src/libacm.c
+@@ -66,45 +66,71 @@ static void acm_set_server_port(void)
+ }
+ }
+
+-int libacm_init(void)
++static char *get_dest(char *arg)
+ {
+- struct sockaddr_in addr;
++ static char addr[64];
++ struct addrinfo hint, *res;
++ const char *ai;
+ int ret;
+
+- ret = osd_init();
++ memset(&hint, 0, sizeof hint);
++ hint.ai_protocol = IPPROTO_TCP;
++ ret = getaddrinfo(arg, NULL, &hint, &res);
++ if (ret) {
++ *format = 'l';
++ return arg;
++ }
++
++ if (res->ai_family == AF_INET) {
++ ai = inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
++ addr, sizeof addr);
++ } else {
++ ai = inet_ntop(AF_INET6, &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr,
++ addr, sizeof addr);
++ }
++ freeaddrinfo(res);
++}
++
++int ib_acm_connect(char *dest)
++{
++ struct addrinfo hint, *res;
++ int ret;
++
++ acm_set_server_port();
++ memset(&hint, 0, sizeof hint);
++ hint.ai_protocol = IPPROTO_TCP;
++ ret = getaddrinfo(dest, NULL, &hint, &res);
+ if (ret)
+ return ret;
+
+- acm_set_server_port();
+- sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
++ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (sock == INVALID_SOCKET) {
+ ret = socket_errno();
+ goto err1;
+ }
+
+- memset(&addr, 0, sizeof addr);
+- addr.sin_family = AF_INET;
+- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+- addr.sin_port = htons(server_port);
+- ret = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
++ ((struct sockaddr_in *) res)->sin_port = htons(server_port);
++ ret = connect(sock, res->ai_addr, res->ai_addrlen);
+ if (ret)
+ goto err2;
+
++ freeaddrinfo(res);
+ return 0;
+
+ err2:
+ closesocket(sock);
+ sock = INVALID_SOCKET;
+ err1:
+- osd_close();
++ freeaddrinfo(res);
+ return ret;
+ }
+
+-void libacm_cleanup(void)
++void ib_acm_disconnect(void)
+ {
+ if (sock != INVALID_SOCKET) {
+ shutdown(sock, SHUT_RDWR);
+ closesocket(sock);
++ sock = INVALID_SOCKET;
+ }
+ }
+
+@@ -310,3 +336,41 @@ out:
+ lock_release(&lock);
+ return ret;
+ }
++
++static int ib_acm_query_perf(uint64_t **counters, int *count)
++{
++ struct acm_msg msg;
++ struct acm_perf_msg *perf_msg = (struct acm_perf_msg *) &msg;
++ int ret, cnt = 0;
++
++ lock_acquire(&lock);
++ memset(&msg, 0, sizeof msg);
++ msg.hdr.version = ACM_VERSION;
++ msg.hdr.opcode = ACM_OP_PERF_QUERY;
++ msg.hdr.length = ACM_MSG_HDR_LENGTH;
++
++ ret = send(sock, (char *) &msg, msg.hdr.length, 0);
++ if (ret != msg.hdr.length)
++ goto out;
++
++ ret = recv(sock, (char *) &msg, sizeof msg, 0);
++ if (ret < ACM_MSG_HDR_LENGTH || ret != msg.hdr.length)
++ goto out;
++
++ if (msg.hdr.status) {
++ ret = acm_error(msg.hdr.status);
++ goto out;
++ }
++
++ *counters = malloc(sizeof(uint64_t) * msg.hdr.data[0]);
++ if (!*counters) {
++ ret = ACM_STATUS_ENOMEM;
++ goto out;
++ }
++
++ memcpy(*counters, perf_msg->data, msg.hdr.data[0]);
++ ret = 0;
++out:
++ lock_release(&lock);
++ return ret;
++}
+diff --git a/src/libacm.h b/src/libacm.h
+index 16df8b0..049b7a9 100644
+--- a/src/libacm.h
++++ b/src/libacm.h
+@@ -27,10 +27,13 @@
+ * SOFTWARE.
+ */
+
++#ifndef LIBACM_H
++#define LIBACM_H
++
+ #include <infiniband/acm.h>
+
+-int libacm_init();
+-void libacm_cleanup();
++int ib_acm_connect(char *dest_svc);
++void ib_acm_disconnect();
+
+ int ib_acm_resolve_name(char *src, char *dest,
+ struct ibv_path_data **paths, int *count, uint32_t flags);
+@@ -38,3 +41,8 @@ int ib_acm_resolve_ip(struct sockaddr *src, struct sockaddr *dest,
+ struct ibv_path_data **paths, int *count, uint32_t flags);
+ int ib_acm_resolve_path(struct ibv_path_record *path, uint32_t flags);
+ #define ib_acm_free_paths(paths) free(paths)
++
++int ib_acm_query_perf(uint64_t **counters, int *count);
++#define ib_acm_free_perf(counters) free(counters)
++
++#endif /* LIBACM_H */