From be5829398787a25b7e39fe8734d217edd51198b4 Mon Sep 17 00:00:00 2001 From: Kaike Wan Date: Fri, 13 Jun 2014 12:35:02 -0700 Subject: [PATCH] ib_acme: Add support for endpoint specific performance query. Adds the following queries to ib_acme tool: ib_acme -P N to query the performance for a specific endpoint N (N = 1, 2, ...); ib_acme -P all to query the performance for all endpoints; ib_acme -f [n | i] -s [src name | ip addr] -P s to query the performance for a specific endpoint with the given address. in addition to the normal query for overal (combined) performance: ib_acme -P ib_acme -P col Signed-off-by: Kaike Wan Signed-off-by: Sean Hefty --- src/acme.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++----- src/libacm.c | 57 +++++++++++++++++++- src/libacm.h | 4 +- 3 files changed, 196 insertions(+), 15 deletions(-) diff --git a/src/acme.c b/src/acme.c index d281319..8279b65 100644 --- a/src/acme.c +++ b/src/acme.c @@ -64,7 +64,10 @@ static int enum_ep; enum perf_query_output { PERF_QUERY_NONE, PERF_QUERY_ROW, - PERF_QUERY_COL + PERF_QUERY_COL, + PERF_QUERY_EP_INDEX, + PERF_QUERY_EP_ALL, + PERF_QUERY_EP_ADDR }; static enum perf_query_output perf_query; int verbose; @@ -90,7 +93,13 @@ static void show_usage(char *program) printf(" [-d dest_addr] - destination addresses for path queries\n"); printf(" [-v] - verify ACM response against SA query response\n"); printf(" [-c] - read ACM cached data only\n"); - printf(" [-P] - query performance data from destination service\n"); + printf(" [-P [opt]] - query performance data from destination service:\n"); + printf(" No option: output combined data in row format.\n"); + printf(" col: output combined data in colum format.\n"); + printf(" N: output data for endpoint N (N = 1, 2,...)\n"); + printf(" all: output data for all endpoints\n"); + printf(" s: output data for the endpoint with the\n"); + printf(" address specified in -s option\n"); printf(" [-S svc_addr] - address of ACM service, default: local service\n"); printf(" [-C repetitions] - repeat count for resolution\n"); printf("usage 2: %s\n", program); @@ -748,24 +757,107 @@ static void resolve(char *svc) free(dest_list); } -static void query_perf(char *svc) +static int query_perf_ip(uint64_t **counters, int *cnt) +{ + union _sockaddr { + struct sockaddr_storage src; + struct sockaddr saddr; + } addr; + uint8_t type; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + int ret; + + VPRINT("%s: src_addr %s\n", __FUNCTION__, src_addr); + addr.saddr.sa_family = AF_INET; + sin = (struct sockaddr_in *) &addr.saddr; + ret = inet_pton(AF_INET, src_addr, &sin->sin_addr); + if (ret <= 0) { + addr.saddr.sa_family = AF_INET6; + sin6 = (struct sockaddr_in6 *)&addr.saddr; + ret = inet_pton(AF_INET6, src_addr, &sin6->sin6_addr); + if (ret <= 0) { + printf("inet_pton error on src address (%s): 0x%x\n", + src_addr, ret); + return -1; + } + type = ACM_EP_INFO_ADDRESS_IP6; + } else { + type = ACM_EP_INFO_ADDRESS_IP; + } + + ret = ib_acm_query_perf_ep_addr((uint8_t *)&addr.src, type, counters, + cnt); + if (ret) { + printf("ib_acm_query_perf failed: %s\n", strerror(errno)); + return ret; + } + + return 0; +} + +static int query_perf_name(uint64_t **counters, int *cnt) +{ + int ret; + + VPRINT("%s: src_addr %s\n", __FUNCTION__, src_addr); + ret = ib_acm_query_perf_ep_addr((uint8_t *)src_addr, ACM_EP_INFO_NAME, + counters, cnt); + if (ret) { + printf("ib_acm_query_perf failed: %s\n", strerror(errno)); + return ret; + } + + return 0; +} + +static int query_perf_ep_addr(uint64_t **counters, int *cnt) +{ + int ret; + char src_type; + + src_addr = get_dest(src_arg, &src_type); + switch (src_type) { + case 'i': + ret = query_perf_ip(counters, cnt); + break; + case 'n': + ret = query_perf_name(counters, cnt); + break; + default: + printf("Unsupported src_type %d\n", src_type); + return -1; + } + + return ret; +} + +static int query_perf_one(char *svc, int index) { - static int lables; + static int labels; int ret, cnt, i; uint64_t *counters; - ret = ib_acm_query_perf(&counters, &cnt); + if (perf_query == PERF_QUERY_EP_ADDR) + ret = query_perf_ep_addr(&counters, &cnt); + else + ret = ib_acm_query_perf(index, &counters, &cnt); + if (ret) { - printf("%s: Failed to query perf data %s\n", svc, strerror(errno)); - return; + if (perf_query != PERF_QUERY_EP_ALL) { + printf("%s: Failed to query perf data: %s\n", svc, + strerror(errno)); + } + return ret; } - if (perf_query == PERF_QUERY_ROW) { - if (!lables) { + if (perf_query != PERF_QUERY_COL) { + if (!labels) { + printf("svc,"); for (i = 0; i < cnt - 1; i++) printf("%s,", ib_acm_cntr_name(i)); printf("%s\n", ib_acm_cntr_name(i)); - lables = 1; + labels = 1; } printf("%s,", svc); for (i = 0; i < cnt - 1; i++) @@ -779,6 +871,20 @@ static void query_perf(char *svc) } } ib_acm_free_perf(counters); + + return 0; +} + +static void query_perf(char *svc) +{ + int index = 1; + + if (perf_query != PERF_QUERY_EP_ALL) { + query_perf_one(svc, ep_index); + } + else { + while (!query_perf_one(svc, index++)); + } } static int enumerate_ep(char *svc, int index) @@ -864,6 +970,23 @@ char *opt_arg(int argc, char **argv) return NULL; } +void parse_perf_arg(char *arg) +{ + if (!strnicmp("col", arg, 3)) { + perf_query = PERF_QUERY_COL; + } else if (!strnicmp("all", arg, 3)) { + perf_query = PERF_QUERY_EP_ALL; + } else if (!strcmp("s", arg)) { + perf_query = PERF_QUERY_EP_ADDR; + } else { + ep_index = atoi(arg); + if (ep_index > 0) + perf_query = PERF_QUERY_EP_INDEX; + else + perf_query = PERF_QUERY_ROW; + } +} + int CDECL_FUNC main(int argc, char **argv) { int op, ret; @@ -913,8 +1036,8 @@ int CDECL_FUNC main(int argc, char **argv) dest_dir = optarg; break; case 'P': - if (opt_arg(argc, argv) && !strnicmp("col", opt_arg(argc, argv), 3)) - perf_query = PERF_QUERY_COL; + if (opt_arg(argc, argv)) + parse_perf_arg(opt_arg(argc, argv)); else perf_query = PERF_QUERY_ROW; break; @@ -934,7 +1057,8 @@ int CDECL_FUNC main(int argc, char **argv) } } - if ((src_arg && !dest_arg) || + if ((src_arg && (!dest_arg && perf_query != PERF_QUERY_EP_ADDR)) || + (perf_query == PERF_QUERY_EP_ADDR && !src_arg) || (!src_arg && !dest_arg && !perf_query && !make_addr && !make_opts && !enum_ep)) goto show_use; diff --git a/src/libacm.c b/src/libacm.c index 16cdead..95e562d 100644 --- a/src/libacm.c +++ b/src/libacm.c @@ -305,7 +305,7 @@ out: return ret; } -int ib_acm_query_perf(uint64_t **counters, int *count) +int ib_acm_query_perf(int index, uint64_t **counters, int *count) { struct acm_msg msg; int ret, i; @@ -314,6 +314,7 @@ int ib_acm_query_perf(uint64_t **counters, int *count) memset(&msg, 0, sizeof msg); msg.hdr.version = ACM_VERSION; msg.hdr.opcode = ACM_OP_PERF_QUERY; + msg.hdr.data[1] = index; msg.hdr.length = htons(ACM_MSG_HDR_LENGTH); ret = send(sock, (char *) &msg, ACM_MSG_HDR_LENGTH, 0); @@ -396,6 +397,60 @@ out: return ret; } +int ib_acm_query_perf_ep_addr(uint8_t *src, uint8_t type, + uint64_t **counters, int *count) +{ + struct acm_msg msg; + int ret, i, len; + + if (!src) + return -1; + + lock_acquire(&lock); + memset(&msg, 0, sizeof msg); + msg.hdr.version = ACM_VERSION; + msg.hdr.opcode = ACM_OP_PERF_QUERY; + + ret = acm_format_ep_addr(&msg.resolve_data[0], src, type, + ACM_EP_FLAG_SOURCE); + if (ret) + goto out; + + len = ACM_MSG_HDR_LENGTH + ACM_MSG_EP_LENGTH; + msg.hdr.length = htons(len); + + ret = send(sock, (char *) &msg, len, 0); + if (ret != len) + goto out; + + ret = recv(sock, (char *) &msg, sizeof msg, 0); + if (ret < ACM_MSG_HDR_LENGTH || ret != ntohs(msg.hdr.length)) { + ret = ACM_STATUS_EINVAL; + 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; + } + + *count = msg.hdr.data[0]; + for (i = 0; i < *count; i++) + (*counters)[i] = ntohll(msg.perf_data[i]); + + ret = 0; +out: + lock_release(&lock); + return ret; +} + + const char *ib_acm_cntr_name(int index) { static const char *const cntr_name[] = { diff --git a/src/libacm.h b/src/libacm.h index e94291f..359a6af 100644 --- a/src/libacm.h +++ b/src/libacm.h @@ -45,7 +45,9 @@ int ib_acm_resolve_ip(struct sockaddr *src, struct sockaddr *dest, 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); +int ib_acm_query_perf(int index, uint64_t **counters, int *count); +int ib_acm_query_perf_ep_addr(uint8_t *src, uint8_t type, + uint64_t **counters, int *count); #define ib_acm_free_perf(counters) free(counters) const char *ib_acm_cntr_name(int index); -- 2.46.0