Version: 1
-Previous: 5e1b972ed933592eb3779554c58c6bbec1eea171
+Previous: d69822e2cce508e915dfc6d6b1a5647a1a9efe23
Head: 697ed433218e6aae1fcb64d26be36e80434b34e6
Applied:
af_ib: 697ed433218e6aae1fcb64d26be36e80434b34e6
Unapplied:
- name2ip: 8e00708e882239292492e13aa51c82042255933c
+ dev-name2ip: 8e00708e882239292492e13aa51c82042255933c
addr_size: 8de02c47fbf595132105a7050ad6f755f49f9a7a
Hidden:
--- /dev/null
+Bottom: e8b5bb1cf92f403d8767fc1d61cb8c538da64fe3
+Top: b51c859aabeb9d4834702625abd3bb4e7dff04cb
+Author: Sean Hefty <sean.hefty@intel.com>
+Date: 2011-04-04 17:29:06 -0700
+
+Translate names to IP addresses
+
+In addition to translating host names directly into IB addresses,
+provide the ability to translate the names into corresponding
+IP addresses. While this allows ib_acm to act as a simple name
+service, it also allows the user to load the ib_acm database using
+host names, while storing the resulting data based on IP addresses.
+This can be useful for large clusters, where a large number of
+systems can easily be specified using syntax similar to
+node[1-1000], whereas an application may relay on a class B IP
+address.
+
+The ib_acme service is updated to allow the user to indicate that
+IP name service translation is requested. In such cases, the user
+inputs a name or address, and a corresponding address is returned.
+
+ib_acm uses the source address type of a request to determine if
+translation should occur. If the source type differs from the
+destination type, ib_acm will convert the destination address
+into one matching the source type and return it with the result.
+
+Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+
+---
+
+diff --git a/include/infiniband/acm.h b/include/infiniband/acm.h
+index 41b95b8..a0ad353 100644
+--- a/include/infiniband/acm.h
++++ b/include/infiniband/acm.h
+@@ -90,7 +90,8 @@ union acm_ep_info
+ struct acm_ep_addr_data
+ {
+ uint32_t flags;
+- uint16_t type;
++ uint8_t out_type;
++ uint8_t type;
+ uint16_t reserved;
+ union acm_ep_info info;
+ };
+diff --git a/src/acm.c b/src/acm.c
+index 53a8e7b..19cf3f8 100644
+--- a/src/acm.c
++++ b/src/acm.c
+@@ -48,6 +48,7 @@
+ #include "acm_mad.h"
+
+ #define src_out reserved[0]
++#define dst_out reserved[1]
+
+ #define MAX_EP_ADDR 4
+ #define MAX_EP_MC 2
+@@ -786,6 +787,17 @@ static int acm_addr_index(struct acm_ep *ep, uint8_t *addr, uint8_t addr_type)
+ return -1;
+ }
+
++static int acm_type_index(struct acm_ep *ep, uint8_t addr_type)
++{
++ int i;
++
++ for (i = 0; i < MAX_EP_ADDR; i++) {
++ if (ep->addr_type[i] == addr_type)
++ return i;
++ }
++ return -1;
++}
++
+ static uint8_t
+ acm_record_acm_route(struct acm_ep *ep, struct acm_dest *dest)
+ {
+@@ -1149,8 +1161,11 @@ acm_process_addr_req(struct acm_ep *ep, struct ibv_wc *wc, struct acm_mad *mad)
+ }
+
+ addr_index = acm_addr_index(ep, rec->dest, rec->dest_type);
+- if (addr_index >= 0)
++ if (addr_index >= 0) {
+ dest->req_id = mad->tid;
++ if (rec->src_type != rec->dest_type)
++ acm_translate_rec_addr(ep, rec, &addr_index);
++ }
+
+ lock_acquire(&dest->lock);
+ acm_log(2, "dest state %d\n", dest->state);
+@@ -1779,6 +1794,48 @@ acm_get_port_ep(struct acm_port *port, struct acm_ep_addr_data *data)
+ return NULL;
+ }
+
++static int acm_translate_addr(struct acm_ep *ep, struct acm_ep_addr_data *data)
++{
++ int i;
++
++ for (i = 0; i < MAX_EP_ADDR; i++) {
++ if (ep->addr_type[i] == data->out_type) {
++ data->type = data->out_type;
++ data->info = ep->addr[i];
++ acm_format_name(2, log_data, sizeof log_data,
++ data->type, data->info.addr, sizeof data->info.addr);
++ acm_log(2, "translated addr %s\n", log_data);
++ return 0;
++ }
++ }
++
++ acm_format_name(1, log_data, sizeof log_data,
++ data->type, data->info.addr, sizeof data->info.addr);
++ acm_log(1, "no translation available for %s\n", log_data);
++ return -1;
++}
++
++static void acm_translate_rec_addr(struct acm_ep *ep, struct acm_resolve_rec *rec,
++ int *addr_index)
++{
++ int i;
++
++ i = acm_type_index(rec->src_type);
++ if (i < 0) {
++ acm_format_name(2, log_data, sizeof log_data,
++ rec->dest_type, rec->dest, sizeof rec->dest);
++ acm_log(0, "notice - no translation for %s\n", log_data);
++ return;
++ }
++
++ rec->dest_type = rec->src_type;
++ memcpy(rec->dest, ep->addr[i].addr, sizeof rec->dest);
++ *addr_index = i;
++ acm_format_name(2, log_data, sizeof log_data,
++ rec->dest_type, rec->dest, sizeof rec->dest);
++ acm_log(0, "translated address to %s\n", log_data);
++}
++
+ static struct acm_ep *
+ acm_get_ep(struct acm_ep_addr_data *data)
+ {
+@@ -1983,6 +2040,7 @@ acm_svr_verify_resolve(struct acm_resolve_msg *msg,
+ struct acm_ep_addr_data **saddr, struct acm_ep_addr_data **daddr)
+ {
+ struct acm_ep_addr_data *src = NULL, *dst = NULL;
++ struct acm_ep_addr_data *data;
+ int i, cnt;
+
+ if (msg->hdr.length < ACM_MSG_HDR_LENGTH) {
+@@ -1992,27 +2050,32 @@ acm_svr_verify_resolve(struct acm_resolve_msg *msg,
+
+ cnt = (msg->hdr.length - ACM_MSG_HDR_LENGTH) / ACM_MSG_EP_LENGTH;
+ for (i = 0; i < cnt; i++) {
+- if (msg->data[i].flags & ACM_EP_FLAG_SOURCE) {
++ data = &msg->data[i];
++ if (data->flags & ACM_EP_FLAG_SOURCE) {
+ if (src) {
+ acm_log(0, "ERROR - multiple sources specified\n");
+ return ACM_STATUS_ESRCADDR;
+ }
+- if (!msg->data[i].type || (msg->data[i].type >= ACM_ADDRESS_RESERVED)) {
++ if (!data->type || (data->type >= ACM_ADDRESS_RESERVED)) {
+ acm_log(0, "ERROR - unsupported source address type\n");
+ return ACM_STATUS_ESRCTYPE;
+ }
+- src = &msg->data[i];
++ src = data;
++ if (src->out_type && (src->out_type < ACM_ADDRESS_RESERVED))
++ msg->hdr.src_out = i;
+ }
+- if (msg->data[i].flags & ACM_EP_FLAG_DEST) {
++ if (data->flags & ACM_EP_FLAG_DEST) {
+ if (dst) {
+ acm_log(0, "ERROR - multiple destinations specified\n");
+ return ACM_STATUS_EDESTADDR;
+ }
+- if (!msg->data[i].type || (msg->data[i].type >= ACM_ADDRESS_RESERVED)) {
++ if (!data->type || (data->type >= ACM_ADDRESS_RESERVED)) {
+ acm_log(0, "ERROR - unsupported destination address type\n");
+ return ACM_STATUS_EDESTTYPE;
+ }
+- dst = &msg->data[i];
++ dst = data;
++ if (dst->out_type && (dst->out_type < ACM_ADDRESS_RESERVED))
++ msg->hdr.dst_out = i;
+ }
+ }
+
+@@ -2079,6 +2142,11 @@ acm_svr_resolve(struct acm_client *client, struct acm_resolve_msg *msg)
+ return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_ESRCADDR);
+ }
+
++ if (saddr->out_type && !acm_translate_addr(ep, saddr)) {
++ acm_log(0, "notice - cannot translate source address\n");
++ return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_ESRCADDR);
++ }
++
+ acm_format_name(2, log_data, sizeof log_data,
+ daddr->type, daddr->info.addr, sizeof daddr->info.addr);
+ acm_log(2, "dest %s\n", log_data);
+diff --git a/src/acme.c b/src/acme.c
+index d42ba81..8138109 100644
+--- a/src/acme.c
++++ b/src/acme.c
+@@ -50,6 +50,7 @@ static char *opts_file = ACM_OPTS_FILE;
+ static char *dest_addr;
+ static char *src_addr;
+ static char addr_type = 'u';
++static char out_addr_type;
+ static int verify;
+ static int nodelay;
+ static int make_addr;
+@@ -68,7 +69,9 @@ static void show_usage(char *program)
+ {
+ printf("usage 1: %s\n", program);
+ printf(" [-f addr_format] - i(p), n(ame), l(id), g(gid), or u(nspecified)\n");
+- printf(" default: 'u'\n");
++ printf(" format of src/dst addr, default: 'u'\n");
++ printf(" [-m addr_format] - i(p)\n");
++ printf(" map src/dest names to IP address";)
+ printf(" [-s src_addr] - format defined by -f option\n");
+ printf(" [-d] dest_addr - format defined by -f option\n");
+ printf(" [-v] - verify ACM response against SA query response\n");
+@@ -421,6 +424,18 @@ static void show_path(struct ibv_path_record *path)
+ printf(" packet lifetime: %d\n", path->packetlifetime & 0x1F);
+ }
+
++static void show_addr(char *name, struct sockaddr *addr)
++{
++ char str_addr[ACM_MAX_ADDRESS];
++
++ if (addr->sa_family) {
++ inet_ntop(addr->sa_family, addr, str_addr, sizeof str_addr);
++ printf("%s (%s)", name, str_addr);
++ } else {
++ printf("%s", name);
++ }
++}
++
+ static uint32_t get_resolve_flags()
+ {
+ uint32_t flags = 0;
+@@ -431,7 +446,7 @@ static uint32_t get_resolve_flags()
+ return flags;
+ }
+
+-static int resolve_ip(struct ibv_path_record *path)
++static int resolve_ip(struct sockaddr *src_out, struct ibv_path_record *path)
+ {
+ struct ibv_path_data *paths;
+ struct sockaddr_in src, dest;
+@@ -446,8 +461,10 @@ static int resolve_ip(struct ibv_path_record *path)
+ return ret;
+ }
+ saddr = (struct sockaddr *) &src;
++ src_out->sa_family = 0;
+ } else {
+ saddr = NULL;
++ src_out->sa_family = AF_INET;
+ }
+
+ dest.sin_family = AF_INET;
+@@ -458,7 +475,7 @@ static int resolve_ip(struct ibv_path_record *path)
+ }
+
+ ret = ib_acm_resolve_ip(saddr, (struct sockaddr *) &dest,
+- &paths, &count, get_resolve_flags());
++ src_out, &paths, &count, get_resolve_flags());
+ if (ret) {
+ printf("ib_acm_resolve_ip failed: %s\n", strerror(errno));
+ return ret;
+@@ -469,12 +486,20 @@ static int resolve_ip(struct ibv_path_record *path)
+ return 0;
+ }
+
+-static int resolve_name(struct ibv_path_record *path)
++static int resolve_name(struct sockaddr *src_out, struct sockaddr *dest_out,
++ struct ibv_path_record *path)
+ {
+ struct ibv_path_data *paths;
+ int ret, count;
+
+- ret = ib_acm_resolve_name(src_addr, dest_addr, &paths, &count, get_resolve_flags());
++ if (out_addr_type) {
++ src_out->sa_family = dest_out->sa_family = AF_INET;
++ } else {
++ src_out->sa_family = dest_out->sa_family = 0;
++ }
++
++ ret = ib_acm_resolve_name(src_addr, dest_addr, src_out, dest_out,
++ &paths, &count, get_resolve_flags());
+ if (ret) {
+ printf("ib_acm_resolve_name failed: %s\n", strerror(errno));
+ return ret;
+@@ -584,6 +609,7 @@ static int resolve(char *program, char *dest_arg)
+ {
+ char **dest_list;
+ struct ibv_path_record path;
++ struct sockaddr_storage src_out, dest_out;
+ int ret, i = 0;
+ char dest_type;
+
+@@ -601,13 +627,14 @@ static int resolve(char *program, char *dest_arg)
+
+ for (dest_addr = get_dest(dest_list[i], &dest_type); dest_addr;
+ dest_addr = get_dest(dest_list[++i], &dest_type)) {
+- printf("Destination: %s\n", dest_addr);
++
+ switch (dest_type) {
+ case 'i':
+- ret = resolve_ip(&path);
++ dest_out->sa_family = 0;
++ ret = resolve_ip(&src_out, &path);
+ break;
+ case 'n':
+- ret = resolve_name(&path);
++ ret = resolve_name(&src_out, &dest_out, &path);
+ break;
+ case 'l':
+ memset(&path, 0, sizeof path);
+@@ -622,11 +649,19 @@ static int resolve(char *program, char *dest_arg)
+ exit(1);
+ }
+
+- if (!ret)
+- show_path(&path);
++ printf("Resolving: ");
++ show_addr(src_addr, &src_out);
++ printf(" -> ");
++ show_addr(dest_addr, &dest_out);
++ printf("\n");
+
+- if (verify)
+- ret = verify_resolve(&path);
++ if (!ret) {
++ show_path(&path);
++ if (verify)
++ ret = verify_resolve(&path);
++ } else {
++ printf("error: %d %s\n", errno, strerror(errno));
++ }
+ printf("\n");
+ }
+
+@@ -660,6 +695,13 @@ int CDECL_FUNC main(int argc, char **argv)
+ case 'f':
+ addr_type = optarg[0];
+ break;
++ case 'm':
++ out_addr_type = optarg[0];
++ if (out_addr_type != 'i') {
++ show_usage(argv[0]);
++ exit(1);
++ }
++ break;
+ case 's':
+ src_addr = optarg;
+ break;
+diff --git a/src/libacm.c b/src/libacm.c
+index c59a8fb..19cec4d 100644
+--- a/src/libacm.c
++++ b/src/libacm.c
+@@ -58,6 +58,12 @@ extern lock_t lock;
+ static SOCKET sock = INVALID_SOCKET;
+ static short server_port = 6125;
+
++static inline int ERR(int err)
++{
++ errno = err;
++ return -1;
++}
++
+ static void acm_set_server_port(void)
+ {
+ FILE *f;
+@@ -110,12 +116,46 @@ void libacm_cleanup(void)
+ }
+ }
+
++static uint8_t acm_get_type(struct sockaddr *addr)
++{
++ if (!addr)
++ return 0;
++
++ switch (addr->sa_family) {
++ case AF_INET: return ACM_EP_INFO_ADDRESS_IP;
++ case AF_INET6: return ACM_EP_INFO_ADDRESS_IP6;
++ default: return 0;
++ }
++}
++
++static int acm_copy_addr(struct sockaddr *addr, struct acm_ep_addr_data *data)
++{
++ if (acm_get_type(addr) != data->type)
++ return ERR(EINVAL);
++
++ switch (data->type) {
++ case ACM_EP_INFO_ADDRESS_IP:
++ memcpy(addr, data->addr, sizeof(struct sockaddr_in));
++ break;
++ case ACM_EP_INFO_ADDRESS_IP6:
++ mempcy(addr, data->addr, sizeof(struct sockaddr_in6));
++ break;
++ case ACM_EP_INFO_NAME:
++ memcpy(addr, data->name, ACM_MAX_ADDRESS);
++ break;
++ default:
++ return ERR(EINVAL);
++ }
++ return 0;
++}
++
+ static int acm_format_resp(struct acm_resolve_msg *msg,
++ struct sockaddr *src_addr, struct sockaddr *dest_addr,
+ struct ibv_path_data **paths, int *count)
+ {
+ struct ibv_path_data *path_data;
+- char addr[ACM_MAX_ADDRESS];
+- int i, addr_cnt;
++ struct acm_ep_addr_data *data;
++ int i, addr_cnt, ret;
+
+ *count = 0;
+ addr_cnt = (msg->hdr.length - ACM_MSG_HDR_LENGTH) /
+@@ -126,31 +166,23 @@ static int acm_format_resp(struct acm_resolve_msg *msg,
+ return -1;
+
+ for (i = 0; i < addr_cnt; i++) {
+- switch (msg->data[i].type) {
+- case ACM_EP_INFO_PATH:
+- path_data[i].flags = msg->data[i].flags;
+- path_data[i].path = msg->data[i].info.path;
++ data = &msg->data[i];
++ if (data->type == ACM_EP_INFO_PATH) {
++ path_data[i].flags = data->flags;
++ path_data[i].path = data->path;
+ (*count)++;
+- break;
+- default:
+- if (!(msg->data[i].flags & ACM_EP_FLAG_SOURCE))
+- goto err;
+-
+- switch (msg->data[i].type) {
+- case ACM_EP_INFO_ADDRESS_IP:
+- inet_ntop(AF_INET, msg->data[i].info.addr, addr, sizeof addr);
+- break;
+- case ACM_EP_INFO_ADDRESS_IP6:
+- inet_ntop(AF_INET6, msg->data[i].info.addr, addr, sizeof addr);
+- break;
+- case ACM_EP_INFO_NAME:
+- memcpy(addr, msg->data[i].info.name, ACM_MAX_ADDRESS);
+- break;
+- default:
+- goto err;
++ } else {
++ if ((data->flags & ACM_EP_FLAG_SOURCE) && src_addr) {
++ ret = acm_copy_addr(src_addr, data);
++ if (ret)
++ goto err;
++ }
++
++ if ((data->flags & ACM_EP_FLAG_DEST) && dest_addr) {
++ ret = acm_copy_addr(dest_addr, data);
++ if (ret)
++ goto err;
+ }
+- printf("Source: %s\n", addr);
+- break;
+ }
+ }
+
+@@ -158,14 +190,15 @@ static int acm_format_resp(struct acm_resolve_msg *msg,
+ return 0;
+ err:
+ free(path_data);
+- return -1;
++ return ret;
+ }
+
+ static int acm_format_ep_addr(struct acm_ep_addr_data *data, uint8_t *addr,
+- uint8_t type, uint32_t flags)
++ uint8_t type, uint8_t out_type, uint32_t flags)
+ {
+- data->type = type;
+- data->flags = flags;
++ data->type = type;
++ data->out_type = out_type;
++ data->flags = flags;
+
+ switch (type) {
+ case ACM_EP_INFO_NAME:
+@@ -184,12 +217,6 @@ static int acm_format_ep_addr(struct acm_ep_addr_data *data, uint8_t *addr,
+ return 0;
+ }
+
+-static inline int ERR(int err)
+-{
+- errno = err;
+- return -1;
+-}
+-
+ static int acm_error(uint8_t status)
+ {
+ switch (status) {
+@@ -216,6 +243,7 @@ static int acm_error(uint8_t status)
+ }
+
+ static int acm_resolve(uint8_t *src, uint8_t *dest, uint8_t type,
++ struct sockaddr *src_out, struct sockaddr *dest_out,
+ struct ibv_path_data **paths, int *count, uint32_t flags)
+ {
+ struct acm_msg msg;
+@@ -229,13 +257,13 @@ static int acm_resolve(uint8_t *src, uint8_t *dest, uint8_t type,
+
+ if (src) {
+ ret = acm_format_ep_addr(&resolve_msg->data[cnt++], src, type,
+- ACM_EP_FLAG_SOURCE);
++ acm_get_type(src_out), ACM_EP_FLAG_SOURCE);
+ if (ret)
+ goto out;
+ }
+
+ ret = acm_format_ep_addr(&resolve_msg->data[cnt++], dest, type,
+- ACM_EP_FLAG_DEST | flags);
++ acm_get_type(dest_out), ACM_EP_FLAG_DEST | flags);
+ if (ret)
+ goto out;
+
+@@ -254,29 +282,26 @@ static int acm_resolve(uint8_t *src, uint8_t *dest, uint8_t type,
+ goto out;
+ }
+
+- ret = acm_format_resp(resolve_msg, paths, count);
++ ret = acm_format_resp(resolve_msg, src_out, dest_out, paths, count);
+ out:
+ lock_release(&lock);
+ return ret;
+ }
+
+ int ib_acm_resolve_name(char *src, char *dest,
++ struct sockaddr *mapped_src, struct sockaddr *mapped_dest,
+ struct ibv_path_data **paths, int *count, uint32_t flags)
+ {
+ return acm_resolve((uint8_t *) src, (uint8_t *) dest,
+- ACM_EP_INFO_NAME, paths, count, flags);
++ ACM_EP_INFO_NAME, mapped_src, mapped_dest, paths, count, flags);
+ }
+
+ int ib_acm_resolve_ip(struct sockaddr *src, struct sockaddr *dest,
++ struct sockaddr *src_out,
+ struct ibv_path_data **paths, int *count, uint32_t flags)
+ {
+- if (((struct sockaddr *) dest)->sa_family == AF_INET) {
+- return acm_resolve((uint8_t *) src, (uint8_t *) dest,
+- ACM_EP_INFO_ADDRESS_IP, paths, count, flags);
+- } else {
+- return acm_resolve((uint8_t *) src, (uint8_t *) dest,
+- ACM_EP_INFO_ADDRESS_IP6, paths, count, flags);
+- }
++ return acm_resolve((uint8_t *) src, (uint8_t *) dest,
++ acm_get_type(dest), src_out, NULL, paths, count, flags);
+ }
+
+ int ib_acm_resolve_path(struct ibv_path_record *path, uint32_t flags)
+diff --git a/src/libacm.h b/src/libacm.h
+index 16df8b0..3f001c5 100644
+--- a/src/libacm.h
++++ b/src/libacm.h
+@@ -33,8 +33,10 @@ int libacm_init();
+ void libacm_cleanup();
+
+ int ib_acm_resolve_name(char *src, char *dest,
++ struct sockaddr *mapped_src, struct sockaddr *mapped_dest,
+ struct ibv_path_data **paths, int *count, uint32_t flags);
+ int ib_acm_resolve_ip(struct sockaddr *src, struct sockaddr *dest,
++ struct sockaddr *src_out,
+ 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)
+++ /dev/null
-Bottom: e8b5bb1cf92f403d8767fc1d61cb8c538da64fe3
-Top: b51c859aabeb9d4834702625abd3bb4e7dff04cb
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2011-04-04 17:29:06 -0700
-
-Translate names to IP addresses
-
-In addition to translating host names directly into IB addresses,
-provide the ability to translate the names into corresponding
-IP addresses. While this allows ib_acm to act as a simple name
-service, it also allows the user to load the ib_acm database using
-host names, while storing the resulting data based on IP addresses.
-This can be useful for large clusters, where a large number of
-systems can easily be specified using syntax similar to
-node[1-1000], whereas an application may relay on a class B IP
-address.
-
-The ib_acme service is updated to allow the user to indicate that
-IP name service translation is requested. In such cases, the user
-inputs a name or address, and a corresponding address is returned.
-
-ib_acm uses the source address type of a request to determine if
-translation should occur. If the source type differs from the
-destination type, ib_acm will convert the destination address
-into one matching the source type and return it with the result.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/include/infiniband/acm.h b/include/infiniband/acm.h
-index 41b95b8..a0ad353 100644
---- a/include/infiniband/acm.h
-+++ b/include/infiniband/acm.h
-@@ -90,7 +90,8 @@ union acm_ep_info
- struct acm_ep_addr_data
- {
- uint32_t flags;
-- uint16_t type;
-+ uint8_t out_type;
-+ uint8_t type;
- uint16_t reserved;
- union acm_ep_info info;
- };
-diff --git a/src/acm.c b/src/acm.c
-index 53a8e7b..19cf3f8 100644
---- a/src/acm.c
-+++ b/src/acm.c
-@@ -48,6 +48,7 @@
- #include "acm_mad.h"
-
- #define src_out reserved[0]
-+#define dst_out reserved[1]
-
- #define MAX_EP_ADDR 4
- #define MAX_EP_MC 2
-@@ -786,6 +787,17 @@ static int acm_addr_index(struct acm_ep *ep, uint8_t *addr, uint8_t addr_type)
- return -1;
- }
-
-+static int acm_type_index(struct acm_ep *ep, uint8_t addr_type)
-+{
-+ int i;
-+
-+ for (i = 0; i < MAX_EP_ADDR; i++) {
-+ if (ep->addr_type[i] == addr_type)
-+ return i;
-+ }
-+ return -1;
-+}
-+
- static uint8_t
- acm_record_acm_route(struct acm_ep *ep, struct acm_dest *dest)
- {
-@@ -1149,8 +1161,11 @@ acm_process_addr_req(struct acm_ep *ep, struct ibv_wc *wc, struct acm_mad *mad)
- }
-
- addr_index = acm_addr_index(ep, rec->dest, rec->dest_type);
-- if (addr_index >= 0)
-+ if (addr_index >= 0) {
- dest->req_id = mad->tid;
-+ if (rec->src_type != rec->dest_type)
-+ acm_translate_rec_addr(ep, rec, &addr_index);
-+ }
-
- lock_acquire(&dest->lock);
- acm_log(2, "dest state %d\n", dest->state);
-@@ -1779,6 +1794,48 @@ acm_get_port_ep(struct acm_port *port, struct acm_ep_addr_data *data)
- return NULL;
- }
-
-+static int acm_translate_addr(struct acm_ep *ep, struct acm_ep_addr_data *data)
-+{
-+ int i;
-+
-+ for (i = 0; i < MAX_EP_ADDR; i++) {
-+ if (ep->addr_type[i] == data->out_type) {
-+ data->type = data->out_type;
-+ data->info = ep->addr[i];
-+ acm_format_name(2, log_data, sizeof log_data,
-+ data->type, data->info.addr, sizeof data->info.addr);
-+ acm_log(2, "translated addr %s\n", log_data);
-+ return 0;
-+ }
-+ }
-+
-+ acm_format_name(1, log_data, sizeof log_data,
-+ data->type, data->info.addr, sizeof data->info.addr);
-+ acm_log(1, "no translation available for %s\n", log_data);
-+ return -1;
-+}
-+
-+static void acm_translate_rec_addr(struct acm_ep *ep, struct acm_resolve_rec *rec,
-+ int *addr_index)
-+{
-+ int i;
-+
-+ i = acm_type_index(rec->src_type);
-+ if (i < 0) {
-+ acm_format_name(2, log_data, sizeof log_data,
-+ rec->dest_type, rec->dest, sizeof rec->dest);
-+ acm_log(0, "notice - no translation for %s\n", log_data);
-+ return;
-+ }
-+
-+ rec->dest_type = rec->src_type;
-+ memcpy(rec->dest, ep->addr[i].addr, sizeof rec->dest);
-+ *addr_index = i;
-+ acm_format_name(2, log_data, sizeof log_data,
-+ rec->dest_type, rec->dest, sizeof rec->dest);
-+ acm_log(0, "translated address to %s\n", log_data);
-+}
-+
- static struct acm_ep *
- acm_get_ep(struct acm_ep_addr_data *data)
- {
-@@ -1983,6 +2040,7 @@ acm_svr_verify_resolve(struct acm_resolve_msg *msg,
- struct acm_ep_addr_data **saddr, struct acm_ep_addr_data **daddr)
- {
- struct acm_ep_addr_data *src = NULL, *dst = NULL;
-+ struct acm_ep_addr_data *data;
- int i, cnt;
-
- if (msg->hdr.length < ACM_MSG_HDR_LENGTH) {
-@@ -1992,27 +2050,32 @@ acm_svr_verify_resolve(struct acm_resolve_msg *msg,
-
- cnt = (msg->hdr.length - ACM_MSG_HDR_LENGTH) / ACM_MSG_EP_LENGTH;
- for (i = 0; i < cnt; i++) {
-- if (msg->data[i].flags & ACM_EP_FLAG_SOURCE) {
-+ data = &msg->data[i];
-+ if (data->flags & ACM_EP_FLAG_SOURCE) {
- if (src) {
- acm_log(0, "ERROR - multiple sources specified\n");
- return ACM_STATUS_ESRCADDR;
- }
-- if (!msg->data[i].type || (msg->data[i].type >= ACM_ADDRESS_RESERVED)) {
-+ if (!data->type || (data->type >= ACM_ADDRESS_RESERVED)) {
- acm_log(0, "ERROR - unsupported source address type\n");
- return ACM_STATUS_ESRCTYPE;
- }
-- src = &msg->data[i];
-+ src = data;
-+ if (src->out_type && (src->out_type < ACM_ADDRESS_RESERVED))
-+ msg->hdr.src_out = i;
- }
-- if (msg->data[i].flags & ACM_EP_FLAG_DEST) {
-+ if (data->flags & ACM_EP_FLAG_DEST) {
- if (dst) {
- acm_log(0, "ERROR - multiple destinations specified\n");
- return ACM_STATUS_EDESTADDR;
- }
-- if (!msg->data[i].type || (msg->data[i].type >= ACM_ADDRESS_RESERVED)) {
-+ if (!data->type || (data->type >= ACM_ADDRESS_RESERVED)) {
- acm_log(0, "ERROR - unsupported destination address type\n");
- return ACM_STATUS_EDESTTYPE;
- }
-- dst = &msg->data[i];
-+ dst = data;
-+ if (dst->out_type && (dst->out_type < ACM_ADDRESS_RESERVED))
-+ msg->hdr.dst_out = i;
- }
- }
-
-@@ -2079,6 +2142,11 @@ acm_svr_resolve(struct acm_client *client, struct acm_resolve_msg *msg)
- return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_ESRCADDR);
- }
-
-+ if (saddr->out_type && !acm_translate_addr(ep, saddr)) {
-+ acm_log(0, "notice - cannot translate source address\n");
-+ return acm_client_resolve_resp(client, msg, NULL, ACM_STATUS_ESRCADDR);
-+ }
-+
- acm_format_name(2, log_data, sizeof log_data,
- daddr->type, daddr->info.addr, sizeof daddr->info.addr);
- acm_log(2, "dest %s\n", log_data);
-diff --git a/src/acme.c b/src/acme.c
-index d42ba81..8138109 100644
---- a/src/acme.c
-+++ b/src/acme.c
-@@ -50,6 +50,7 @@ static char *opts_file = ACM_OPTS_FILE;
- static char *dest_addr;
- static char *src_addr;
- static char addr_type = 'u';
-+static char out_addr_type;
- static int verify;
- static int nodelay;
- static int make_addr;
-@@ -68,7 +69,9 @@ static void show_usage(char *program)
- {
- printf("usage 1: %s\n", program);
- printf(" [-f addr_format] - i(p), n(ame), l(id), g(gid), or u(nspecified)\n");
-- printf(" default: 'u'\n");
-+ printf(" format of src/dst addr, default: 'u'\n");
-+ printf(" [-m addr_format] - i(p)\n");
-+ printf(" map src/dest names to IP address";)
- printf(" [-s src_addr] - format defined by -f option\n");
- printf(" [-d] dest_addr - format defined by -f option\n");
- printf(" [-v] - verify ACM response against SA query response\n");
-@@ -421,6 +424,18 @@ static void show_path(struct ibv_path_record *path)
- printf(" packet lifetime: %d\n", path->packetlifetime & 0x1F);
- }
-
-+static void show_addr(char *name, struct sockaddr *addr)
-+{
-+ char str_addr[ACM_MAX_ADDRESS];
-+
-+ if (addr->sa_family) {
-+ inet_ntop(addr->sa_family, addr, str_addr, sizeof str_addr);
-+ printf("%s (%s)", name, str_addr);
-+ } else {
-+ printf("%s", name);
-+ }
-+}
-+
- static uint32_t get_resolve_flags()
- {
- uint32_t flags = 0;
-@@ -431,7 +446,7 @@ static uint32_t get_resolve_flags()
- return flags;
- }
-
--static int resolve_ip(struct ibv_path_record *path)
-+static int resolve_ip(struct sockaddr *src_out, struct ibv_path_record *path)
- {
- struct ibv_path_data *paths;
- struct sockaddr_in src, dest;
-@@ -446,8 +461,10 @@ static int resolve_ip(struct ibv_path_record *path)
- return ret;
- }
- saddr = (struct sockaddr *) &src;
-+ src_out->sa_family = 0;
- } else {
- saddr = NULL;
-+ src_out->sa_family = AF_INET;
- }
-
- dest.sin_family = AF_INET;
-@@ -458,7 +475,7 @@ static int resolve_ip(struct ibv_path_record *path)
- }
-
- ret = ib_acm_resolve_ip(saddr, (struct sockaddr *) &dest,
-- &paths, &count, get_resolve_flags());
-+ src_out, &paths, &count, get_resolve_flags());
- if (ret) {
- printf("ib_acm_resolve_ip failed: %s\n", strerror(errno));
- return ret;
-@@ -469,12 +486,20 @@ static int resolve_ip(struct ibv_path_record *path)
- return 0;
- }
-
--static int resolve_name(struct ibv_path_record *path)
-+static int resolve_name(struct sockaddr *src_out, struct sockaddr *dest_out,
-+ struct ibv_path_record *path)
- {
- struct ibv_path_data *paths;
- int ret, count;
-
-- ret = ib_acm_resolve_name(src_addr, dest_addr, &paths, &count, get_resolve_flags());
-+ if (out_addr_type) {
-+ src_out->sa_family = dest_out->sa_family = AF_INET;
-+ } else {
-+ src_out->sa_family = dest_out->sa_family = 0;
-+ }
-+
-+ ret = ib_acm_resolve_name(src_addr, dest_addr, src_out, dest_out,
-+ &paths, &count, get_resolve_flags());
- if (ret) {
- printf("ib_acm_resolve_name failed: %s\n", strerror(errno));
- return ret;
-@@ -584,6 +609,7 @@ static int resolve(char *program, char *dest_arg)
- {
- char **dest_list;
- struct ibv_path_record path;
-+ struct sockaddr_storage src_out, dest_out;
- int ret, i = 0;
- char dest_type;
-
-@@ -601,13 +627,14 @@ static int resolve(char *program, char *dest_arg)
-
- for (dest_addr = get_dest(dest_list[i], &dest_type); dest_addr;
- dest_addr = get_dest(dest_list[++i], &dest_type)) {
-- printf("Destination: %s\n", dest_addr);
-+
- switch (dest_type) {
- case 'i':
-- ret = resolve_ip(&path);
-+ dest_out->sa_family = 0;
-+ ret = resolve_ip(&src_out, &path);
- break;
- case 'n':
-- ret = resolve_name(&path);
-+ ret = resolve_name(&src_out, &dest_out, &path);
- break;
- case 'l':
- memset(&path, 0, sizeof path);
-@@ -622,11 +649,19 @@ static int resolve(char *program, char *dest_arg)
- exit(1);
- }
-
-- if (!ret)
-- show_path(&path);
-+ printf("Resolving: ");
-+ show_addr(src_addr, &src_out);
-+ printf(" -> ");
-+ show_addr(dest_addr, &dest_out);
-+ printf("\n");
-
-- if (verify)
-- ret = verify_resolve(&path);
-+ if (!ret) {
-+ show_path(&path);
-+ if (verify)
-+ ret = verify_resolve(&path);
-+ } else {
-+ printf("error: %d %s\n", errno, strerror(errno));
-+ }
- printf("\n");
- }
-
-@@ -660,6 +695,13 @@ int CDECL_FUNC main(int argc, char **argv)
- case 'f':
- addr_type = optarg[0];
- break;
-+ case 'm':
-+ out_addr_type = optarg[0];
-+ if (out_addr_type != 'i') {
-+ show_usage(argv[0]);
-+ exit(1);
-+ }
-+ break;
- case 's':
- src_addr = optarg;
- break;
-diff --git a/src/libacm.c b/src/libacm.c
-index c59a8fb..19cec4d 100644
---- a/src/libacm.c
-+++ b/src/libacm.c
-@@ -58,6 +58,12 @@ extern lock_t lock;
- static SOCKET sock = INVALID_SOCKET;
- static short server_port = 6125;
-
-+static inline int ERR(int err)
-+{
-+ errno = err;
-+ return -1;
-+}
-+
- static void acm_set_server_port(void)
- {
- FILE *f;
-@@ -110,12 +116,46 @@ void libacm_cleanup(void)
- }
- }
-
-+static uint8_t acm_get_type(struct sockaddr *addr)
-+{
-+ if (!addr)
-+ return 0;
-+
-+ switch (addr->sa_family) {
-+ case AF_INET: return ACM_EP_INFO_ADDRESS_IP;
-+ case AF_INET6: return ACM_EP_INFO_ADDRESS_IP6;
-+ default: return 0;
-+ }
-+}
-+
-+static int acm_copy_addr(struct sockaddr *addr, struct acm_ep_addr_data *data)
-+{
-+ if (acm_get_type(addr) != data->type)
-+ return ERR(EINVAL);
-+
-+ switch (data->type) {
-+ case ACM_EP_INFO_ADDRESS_IP:
-+ memcpy(addr, data->addr, sizeof(struct sockaddr_in));
-+ break;
-+ case ACM_EP_INFO_ADDRESS_IP6:
-+ mempcy(addr, data->addr, sizeof(struct sockaddr_in6));
-+ break;
-+ case ACM_EP_INFO_NAME:
-+ memcpy(addr, data->name, ACM_MAX_ADDRESS);
-+ break;
-+ default:
-+ return ERR(EINVAL);
-+ }
-+ return 0;
-+}
-+
- static int acm_format_resp(struct acm_resolve_msg *msg,
-+ struct sockaddr *src_addr, struct sockaddr *dest_addr,
- struct ibv_path_data **paths, int *count)
- {
- struct ibv_path_data *path_data;
-- char addr[ACM_MAX_ADDRESS];
-- int i, addr_cnt;
-+ struct acm_ep_addr_data *data;
-+ int i, addr_cnt, ret;
-
- *count = 0;
- addr_cnt = (msg->hdr.length - ACM_MSG_HDR_LENGTH) /
-@@ -126,31 +166,23 @@ static int acm_format_resp(struct acm_resolve_msg *msg,
- return -1;
-
- for (i = 0; i < addr_cnt; i++) {
-- switch (msg->data[i].type) {
-- case ACM_EP_INFO_PATH:
-- path_data[i].flags = msg->data[i].flags;
-- path_data[i].path = msg->data[i].info.path;
-+ data = &msg->data[i];
-+ if (data->type == ACM_EP_INFO_PATH) {
-+ path_data[i].flags = data->flags;
-+ path_data[i].path = data->path;
- (*count)++;
-- break;
-- default:
-- if (!(msg->data[i].flags & ACM_EP_FLAG_SOURCE))
-- goto err;
--
-- switch (msg->data[i].type) {
-- case ACM_EP_INFO_ADDRESS_IP:
-- inet_ntop(AF_INET, msg->data[i].info.addr, addr, sizeof addr);
-- break;
-- case ACM_EP_INFO_ADDRESS_IP6:
-- inet_ntop(AF_INET6, msg->data[i].info.addr, addr, sizeof addr);
-- break;
-- case ACM_EP_INFO_NAME:
-- memcpy(addr, msg->data[i].info.name, ACM_MAX_ADDRESS);
-- break;
-- default:
-- goto err;
-+ } else {
-+ if ((data->flags & ACM_EP_FLAG_SOURCE) && src_addr) {
-+ ret = acm_copy_addr(src_addr, data);
-+ if (ret)
-+ goto err;
-+ }
-+
-+ if ((data->flags & ACM_EP_FLAG_DEST) && dest_addr) {
-+ ret = acm_copy_addr(dest_addr, data);
-+ if (ret)
-+ goto err;
- }
-- printf("Source: %s\n", addr);
-- break;
- }
- }
-
-@@ -158,14 +190,15 @@ static int acm_format_resp(struct acm_resolve_msg *msg,
- return 0;
- err:
- free(path_data);
-- return -1;
-+ return ret;
- }
-
- static int acm_format_ep_addr(struct acm_ep_addr_data *data, uint8_t *addr,
-- uint8_t type, uint32_t flags)
-+ uint8_t type, uint8_t out_type, uint32_t flags)
- {
-- data->type = type;
-- data->flags = flags;
-+ data->type = type;
-+ data->out_type = out_type;
-+ data->flags = flags;
-
- switch (type) {
- case ACM_EP_INFO_NAME:
-@@ -184,12 +217,6 @@ static int acm_format_ep_addr(struct acm_ep_addr_data *data, uint8_t *addr,
- return 0;
- }
-
--static inline int ERR(int err)
--{
-- errno = err;
-- return -1;
--}
--
- static int acm_error(uint8_t status)
- {
- switch (status) {
-@@ -216,6 +243,7 @@ static int acm_error(uint8_t status)
- }
-
- static int acm_resolve(uint8_t *src, uint8_t *dest, uint8_t type,
-+ struct sockaddr *src_out, struct sockaddr *dest_out,
- struct ibv_path_data **paths, int *count, uint32_t flags)
- {
- struct acm_msg msg;
-@@ -229,13 +257,13 @@ static int acm_resolve(uint8_t *src, uint8_t *dest, uint8_t type,
-
- if (src) {
- ret = acm_format_ep_addr(&resolve_msg->data[cnt++], src, type,
-- ACM_EP_FLAG_SOURCE);
-+ acm_get_type(src_out), ACM_EP_FLAG_SOURCE);
- if (ret)
- goto out;
- }
-
- ret = acm_format_ep_addr(&resolve_msg->data[cnt++], dest, type,
-- ACM_EP_FLAG_DEST | flags);
-+ acm_get_type(dest_out), ACM_EP_FLAG_DEST | flags);
- if (ret)
- goto out;
-
-@@ -254,29 +282,26 @@ static int acm_resolve(uint8_t *src, uint8_t *dest, uint8_t type,
- goto out;
- }
-
-- ret = acm_format_resp(resolve_msg, paths, count);
-+ ret = acm_format_resp(resolve_msg, src_out, dest_out, paths, count);
- out:
- lock_release(&lock);
- return ret;
- }
-
- int ib_acm_resolve_name(char *src, char *dest,
-+ struct sockaddr *mapped_src, struct sockaddr *mapped_dest,
- struct ibv_path_data **paths, int *count, uint32_t flags)
- {
- return acm_resolve((uint8_t *) src, (uint8_t *) dest,
-- ACM_EP_INFO_NAME, paths, count, flags);
-+ ACM_EP_INFO_NAME, mapped_src, mapped_dest, paths, count, flags);
- }
-
- int ib_acm_resolve_ip(struct sockaddr *src, struct sockaddr *dest,
-+ struct sockaddr *src_out,
- struct ibv_path_data **paths, int *count, uint32_t flags)
- {
-- if (((struct sockaddr *) dest)->sa_family == AF_INET) {
-- return acm_resolve((uint8_t *) src, (uint8_t *) dest,
-- ACM_EP_INFO_ADDRESS_IP, paths, count, flags);
-- } else {
-- return acm_resolve((uint8_t *) src, (uint8_t *) dest,
-- ACM_EP_INFO_ADDRESS_IP6, paths, count, flags);
-- }
-+ return acm_resolve((uint8_t *) src, (uint8_t *) dest,
-+ acm_get_type(dest), src_out, NULL, paths, count, flags);
- }
-
- int ib_acm_resolve_path(struct ibv_path_record *path, uint32_t flags)
-diff --git a/src/libacm.h b/src/libacm.h
-index 16df8b0..3f001c5 100644
---- a/src/libacm.h
-+++ b/src/libacm.h
-@@ -33,8 +33,10 @@ int libacm_init();
- void libacm_cleanup();
-
- int ib_acm_resolve_name(char *src, char *dest,
-+ struct sockaddr *mapped_src, struct sockaddr *mapped_dest,
- struct ibv_path_data **paths, int *count, uint32_t flags);
- int ib_acm_resolve_ip(struct sockaddr *src, struct sockaddr *dest,
-+ struct sockaddr *src_out,
- 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)