[ofa-general] [RFC] 4/5: IB ACM: ib_acme test/configuration utility

Sean Hefty sean.hefty at intel.com
Wed Sep 16 23:54:18 PDT 2009


Add a test/configuration utility to setup the ib_acm service and verify
its operation.

Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
One of the eventual goals is for the librdmacm library to use the ib acm, so
a decision was made to avoid the ib acm package needing to depend on the
librdmacm.  This lead to OS specific code being needed to map IP addresses
to IB endpoints.  If anyone has an easier solution for handling this mapping,
I'm open to alternatives here.

acme.c: OS independent source file

/*
 * Copyright (c) 2009 Intel Corporation.  All rights reserved.
 *
 * This software is available to you under the OpenIB.org BSD license
 * below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <arpa/inet.h>

#include <osd.h>
#include <infiniband/verbs.h>
#include <infiniband/ib_acm.h>

static char *dest_addr;
static char *src_addr;
static char addr_type = 'i';
static int verify;
static int make_addr;
static int make_opts;

struct ibv_context **verbs;
int dev_cnt;

extern int gen_addr_ip(FILE *f);


static void show_usage(char *program)
{
	printf("usage 1: %s\n", program);
	printf("   [-f addr_format] - i(p), n(ame), or l(id)\n");
	printf("                      default: 'i'\n");
	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");
	printf("usage 2: %s\n", program);
	printf("   -A               - generate local acm_addr.cfg configuration file\n");
	printf("   -O               - generate local acm_ops.cfg options file\n");
}

static void gen_opts_temp(FILE *f)
{
	fprintf(f, "# InfiniBand Multicast Communication Manager for clusters configuration file\n");
	fprintf(f, "#\n");
	fprintf(f, "# Use ib_acme utility with -O option to automatically generate a sample\n");
	fprintf(f, "# acm_opts.cfg file for the current system.\n");
	fprintf(f, "#\n");
	fprintf(f, "# Entry format is:\n");
	fprintf(f, "# name value\n");
	fprintf(f, "\n");
	fprintf(f, "# log_file:\n");
	fprintf(f, "# Specifies the location of the ACM service output.  The log file is used to\n");
	fprintf(f, "# assist with ACM service debugging and troubleshooting.  The log_file can\n");
	fprintf(f, "# be set to 'stdout', 'stderr', or the base name of a file.  If a file name\n");
	fprintf(f, "# is specified, the actual name formed by appending a process ID and '.log'\n");
	fprintf(f, "# extension to the end of the specified file name.\n");
	fprintf(f, "# Examples:\n");
	fprintf(f, "# log_file stdout\n");
	fprintf(f, "# log_file stderr\n");
	fprintf(f, "# log_file /tmp/acm_\n");
	fprintf(f, "\n");
	fprintf(f, "log_file stdout\n");
	fprintf(f, "\n");
	fprintf(f, "# log_level:\n");
	fprintf(f, "# Indicates the amount of detailed data written to the log file.  Log levels\n");
	fprintf(f, "# should be one of the following values:\n");
	fprintf(f, "# 0 - basic configuration & errors\n");
	fprintf(f, "# 1 - verbose configuation & errors\n");
	fprintf(f, "# 2 - verbose operation\n");
	fprintf(f, "\n");
	fprintf(f, "log_level 0\n");
	fprintf(f, "\n");
	fprintf(f, "# server_port:\n");
	fprintf(f, "# TCP port number that the server listens on.\n");
	fprintf(f, "# If this value is changed, then a corresponding change is required for\n");
	fprintf(f, "# client applications.\n");
	fprintf(f, "\n");
	fprintf(f, "server_port 6125\n");
	fprintf(f, "\n");
	fprintf(f, "# timeout:\n");
	fprintf(f, "# Additional time, in milliseconds, that the ACM service will wait for a\n");
	fprintf(f, "# response from a remote ACM service or the IB SA.  The actual request\n");
	fprintf(f, "# timeout is this value plus the subnet timeout.\n");
	fprintf(f, "\n");
	fprintf(f, "timeout 2000\n");
	fprintf(f, "\n");
	fprintf(f, "# retries:\n");
	fprintf(f, "# Number of times that the ACM service will retry a request.  This affects\n");
	fprintf(f, "# both ACM multicast messages and and IB SA messages.\n");
	fprintf(f, "\n");
	fprintf(f, "retries 15\n");
	fprintf(f, "\n");
	fprintf(f, "# send_depth:\n");
	fprintf(f, "# Specifies the maximum number of outstanding requests that can be in\n");
	fprintf(f, "# progress simultaneously.  A larger send depth allows for greater\n");
	fprintf(f, "# parallelism, but increases system resource usage and subnet load.\n");
	fprintf(f, "# If the number of pending requests is greater than the send_depth,\n");
	fprintf(f, "# the additional requests will automatically be queued until some of\n");
	fprintf(f, "# the previous requests complete.\n");
	fprintf(f, "\n");
	fprintf(f, "send_depth 8\n");
	fprintf(f, "\n");
	fprintf(f, "# recv_depth:\n");
	fprintf(f, "# Specifies the number of buffers allocated and ready to receive remote\n");
	fprintf(f, "# requests.  A larger receive depth consumes more system resources, but\n");
	fprintf(f, "# can avoid dropping requests due to insufficient receive buffers.\n");
	fprintf(f, "\n");
	fprintf(f, "recv_depth 1024\n");
	fprintf(f, "\n");
	fprintf(f, "# min_mtu:\n");
	fprintf(f, "# Indicates the minimum MTU supported by the ACM service.  The ACM service\n");
	fprintf(f, "# negotiates to use the largest MTU available between both sides of a\n");
	fprintf(f, "# connection.  It is most efficient and recommended that min_mtu be set\n");
	fprintf(f, "# to the largest MTU value supported by all nodes in a cluster.\n");
	fprintf(f, "\n");
	fprintf(f, "min_mtu 2048\n");
	fprintf(f, "\n");
	fprintf(f, "#min_rate:\n");
	fprintf(f, "# Indicates the minimum link rate, in Gbps, supported by the ACM service.\n");
	fprintf(f, "# The ACM service negotiates to use the highest rate available between both\n");
	fprintf(f, "# sides of a connection.  It is most efficient and recommended that the\n");
	fprintf(f, "# min_rate be set to the largest rate supported by all nodes in a cluster.\n");
	fprintf(f, "\n");
	fprintf(f, "min_rate 10\n");
	fprintf(f, "\n");
}

static int gen_opts(void)
{
	FILE *f;

	printf("Generating acm_opts.cfg\n");
	if (!(f = fopen("acm_opts.cfg", "w"))) {
		printf("Failed to open option configuration file\n");
		return -1;
	}

	gen_opts_temp(f);
	fclose(f);
	return 0;
}

static void gen_addr_temp(FILE *f)
{
	fprintf(f, "# InfiniBand Communication Management Assistant for clusters address file\n");
	fprintf(f, "#\n");
	fprintf(f, "# Use ib_acme utility with -G option to automatically generate a sample\n");
	fprintf(f, "# acm_addr.cfg file for the current system.\n");
	fprintf(f, "#\n");
	fprintf(f, "# Entry format is:\n");
	fprintf(f, "# address device port pkey\n");
	fprintf(f, "#\n");
	fprintf(f, "# The address may be one of the following:\n");
	fprintf(f, "# host_name - ascii character string, up to 31 characters\n");
	fprintf(f, "# address - IPv4 or IPv6 formatted address\n");
	fprintf(f, "#\n");
	fprintf(f, "# device name - struct ibv_device name\n");
	fprintf(f, "# port number - valid port number on device (numbering starts at 1)\n");
	fprintf(f, "# pkey - partition key in hex (can specify 'default' for pkey 0xFFFF)\n");
	fprintf(f, "#\n");
	fprintf(f, "# Up to 4 addresses can be associated with a given <device, port, pkey> tuple\n");
	fprintf(f, "#\n");
	fprintf(f, "# Samples:\n");
	fprintf(f, "# node31      ibv_device0 1 default\n");
	fprintf(f, "# node31-1    ibv_device0 1 0x00FF\n");
	fprintf(f, "# node31-2    ibv_device0 2 0x00FF\n");
	fprintf(f, "# 192.168.0.1 ibv_device0 1 0xFFFF\n");
	fprintf(f, "# 192.168.0.2 ibv_device0 2 default\n");
}

static int open_verbs(void)
{
	struct ibv_device **dev_array;
	int i, ret;

	dev_array = ibv_get_device_list(&dev_cnt);
	if (!dev_array) {
		printf("ibv_get_device_list - no devices present?\n");
		return -1;
	}

	verbs = malloc(sizeof(struct ibv_context *) * dev_cnt);
	if (!verbs) {
		ret = -1;
		goto err1;
	}

	for (i = 0; i < dev_cnt; i++) {
		verbs[i] = ibv_open_device(dev_array[i]);
		if (!verbs) {
			printf("ibv_open_device - failed to open device\n");
			ret = -1;
			goto err2;
		}
	}

	ibv_free_device_list(dev_array);
	return 0;

err2:
	while (i--)
		ibv_close_device(verbs[i]);
	free(verbs);
err1:
	ibv_free_device_list(dev_array);
	return ret;
}

static void close_verbs(void)
{
	int i;

	for (i = 0; i < dev_cnt; i++)
		ibv_close_device(verbs[i]);
	free(verbs);
}

static int gen_addr_names(FILE *f)
{
	struct ibv_device_attr dev_attr;
	struct ibv_port_attr port_attr;
	int i, index, ret, found_active;
	char host_name[256];
	uint8_t p;

	ret = gethostname(host_name, sizeof host_name);
	if (ret) {
		printf("gethostname error: %d\n", ret);
		return ret;
	}
	strtok(host_name, ".");

	found_active = 0;
	index = 1;
	for (i = 0; i < dev_cnt; i++) {
		ret = ibv_query_device(verbs[i], &dev_attr);
		if (ret)
			break;

		for (p = 1; p <= dev_attr.phys_port_cnt; p++) {
			if (!found_active) {
				ret = ibv_query_port(verbs[i], p, &port_attr);
				if (!ret && port_attr.state == IBV_PORT_ACTIVE) {
					printf("%s %s %d default\n",
						host_name, verbs[i]->device->name, p);
					fprintf(f, "%s %s %d default\n",
						host_name, verbs[i]->device->name, p);
					found_active = 1;
				}
			}

			printf("%s-%d %s %d default\n",
				host_name, index, verbs[i]->device->name, p);
			fprintf(f, "%s-%d %s %d default\n",
				host_name, index++, verbs[i]->device->name, p);
		}
	}

	return ret;
}

static int gen_addr(void)
{
	FILE *f;
	int ret;

	printf("Generating acm_addr.cfg\n");
	if (!(f = fopen("acm_addr.cfg", "w"))) {
		printf("Failed to open address configuration file\n");
		return -1;
	}

	ret = open_verbs();
	if (ret) {
		goto out1;
	}

	gen_addr_temp(f);
	ret = gen_addr_names(f);
	if (ret) {
		printf("Failed to auto generate host names in config file\n");
		goto out2;
	}

	ret = gen_addr_ip(f);
	if (ret) {
		printf("Failed to auto generate IP addresses in config file\n");
		goto out2;
	}

out2:
	close_verbs();
out1:
	fclose(f);
	return ret;
}

static void show_path(struct ib_path_record *path)
{
	char gid[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
	uint32_t fl_hop;

	printf("Path information\n");
	inet_ntop(AF_INET6, path->dgid.raw, gid, sizeof gid);
	printf("  dgid: %s\n", gid);
	inet_ntop(AF_INET6, path->sgid.raw, gid, sizeof gid);
	printf("  sgid: %s\n", gid);
	printf("  dlid: 0x%x\n", ntohs(path->dlid));
	printf("  slid: 0x%x\n", ntohs(path->slid));
	fl_hop = ntohl(path->flowlabel_hoplimit);
	printf("  flow label: 0x%x\n", fl_hop >> 8);
	printf("  hop limit: %d\n", (uint8_t) fl_hop);
	printf("  tclass: %d\n", path->tclass);
	printf("  reverisible: %d\n", path->reversible_numpath >> 7);
	printf("  pkey: 0x%x\n", ntohs(path->pkey));
	printf("  sl: %d\n", ntohs(path->qosclass_sl) & 0xF);
	printf("  mtu: %d\n", path->mtu & 0x1F);
	printf("  rate: %d\n", path->rate & 0x1F);
	printf("  packet lifetime: %d\n", path->packetlifetime & 0x1F);
}

static int resolve_ip(struct ib_path_record *path)
{
	struct ib_acm_dev_addr dev_addr;
	struct ibv_ah_attr ah;
	struct ib_acm_resolve_data data;
	struct sockaddr_in src, dest;
	int ret;

	src.sin_family = AF_INET;
	ret = inet_pton(AF_INET, src_addr, &src.sin_addr);
	if (ret <= 0) {
		printf("inet_pton error on source address (%s): 0x%x\n", src_addr, ret);
		return ret;
	}

	dest.sin_family = AF_INET;
	ret = inet_pton(AF_INET, dest_addr, &dest.sin_addr);
	if (ret <= 0) {
		printf("inet_pton error on destination address (%s): 0x%x\n", dest_addr, ret);
		return ret;
	}

	ret = ib_acm_resolve_ip((struct sockaddr *) &src, (struct sockaddr *) &dest,
		&dev_addr, &ah, &data);
	if (ret) {
		printf("ib_acm_resolve_ip failed: 0x%x\n", ret);
		return ret;
	}

	ret = ib_acm_convert_to_path(&dev_addr, &ah, &data, path);
	if (ret)
		printf("ib_acm_convert_to_path failed: 0x%x\n", ret);

	return ret;
}

static int resolve_name(struct ib_path_record *path)
{
	struct ib_acm_dev_addr dev_addr;
	struct ibv_ah_attr ah;
	struct ib_acm_resolve_data data;
	int ret;

	ret = ib_acm_resolve_name(src_addr, dest_addr, &dev_addr, &ah, &data);
	if (ret) {
		printf("ib_acm_resolve_name failed: 0x%x\n", ret);
		return ret;
	}

	ret = ib_acm_convert_to_path(&dev_addr, &ah, &data, path);
	if (ret)
		printf("ib_acm_convert_to_path failed: 0x%x\n", ret);

	return ret;
}

static int resolve_lid(struct ib_path_record *path)
{
	int ret;

	path->slid = htons((uint16_t) atoi(src_addr));
	path->dlid = htons((uint16_t) atoi(dest_addr));
	path->reversible_numpath = IB_PATH_RECORD_REVERSIBLE | 1;

	ret = ib_acm_resolve_path(path);
	if (ret)
		printf("ib_acm_resolve_path failed: 0x%x\n", ret);

	return ret;
}

static int verify_resolve(struct ib_path_record *path)
{
	int ret;

	ret = ib_acm_query_path(path);
	if (ret)
		printf("SA verification: failed 0x%x\n", ret);
	else
		printf("SA verification: success\n");

	return ret;
}

static int resolve(char *program)
{
	struct ib_path_record path;
	int ret;

	switch (addr_type) {
	case 'i':
		ret = resolve_ip(&path);
		break;
	case 'n':
		ret = resolve_name(&path);
		break;
	case 'l':
		memset(&path, 0, sizeof path);
		ret = resolve_lid(&path);
		break;
	default:
		show_usage(program);
		exit(1);
	}

	if (!ret)
		show_path(&path);

	if (verify)
		ret = verify_resolve(&path);

	return ret;
}

int main(int argc, char **argv)
{
	int op, ret;

	ret = osd_init();
	if (ret)
		goto out;

	while ((op = getopt(argc, argv, "f:s:d:vAO")) != -1) {
		switch (op) {
		case 'f':
			addr_type = optarg[0];
			break;
		case 's':
			src_addr = optarg;
			break;
		case 'd':
			dest_addr = optarg;
			break;
		case 'v':
			verify = 1;
			break;
		case 'A':
			make_addr = 1;
			break;
		case 'O':
			make_opts = 1;
			break;
		default:
			show_usage(argv[0]);
			exit(1);
		}
	}

	if ((src_addr && !dest_addr) || (dest_addr && !src_addr) ||
		(!src_addr && !dest_addr && !make_addr && !make_opts)) {
		show_usage(argv[0]);
		exit(1);
	}

	if (src_addr)
		ret = resolve(argv[0]);

	if (!ret && make_addr)
		ret = gen_addr();

	if (!ret && make_opts)
		ret = gen_opts();

out:
	printf("return status 0x%x\n", ret);
	return ret;
}


acme_linux.c: Linux implementation to map IP addresses to IB endpoints.
I'm less than thrilled about this code.

/*
 * Copyright (c) 2009 Intel Corporation. All rights reserved.
 *
 * This software is available to you under the OpenIB.org BSD license
 * below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <infiniband/verbs.h>
#include <infiniband/ib_acm.h>

extern struct ibv_context **verbs;
extern int dev_cnt;


static int
get_pkey(struct ifreq *ifreq, uint16_t *pkey)
{
	char buf[128], *end;
	FILE *f;
	int ret;

	sprintf(buf, "//sys//class//net//%s//pkey", ifreq->ifr_name);
	f = fopen(buf, "r");
	if (!f) {
		printf("failed to open %s\n", buf);
		return -1;
	}

	if (fgets(buf, sizeof buf, f)) {
		*pkey = strtol(buf, &end, 16);
		ret = 0;
	} else {
		printf("failed to read pkey\n");
		ret = -1;
	}	

	fclose(f);
	return ret;
}

static int
get_sgid(struct ifreq *ifr, union ibv_gid *sgid)
{
	char buf[128], *end;
	FILE *f;
	int i, p, ret;

	sprintf(buf, "//sys//class//net//%s//address", ifr->ifr_name);
	f = fopen(buf, "r");
	if (!f) {
		printf("failed to open %s\n", buf);
		return -1;
	}

	if (fgets(buf, sizeof buf, f)) {
		for (i = 0, p = 12; i < 16; i++, p += 3) {
			buf[p + 2] = '\0';
			sgid->raw[i] = (uint8_t) strtol(buf + p, &end, 16);
		}
 		ret = 0;
	} else {
		printf("failed to read sgid\n");
		ret = -1;
	}

	fclose(f);
	return ret;
}

static int
get_devaddr(int s, struct ifreq *ifr,
	int *dev_index, uint8_t *port, uint16_t *pkey)
{
	struct ibv_device_attr dev_attr;
	struct ibv_port_attr port_attr;
	union ibv_gid sgid, gid;
	int ret, i;

	ret = get_sgid(ifr, &sgid);
	if (ret) {
		printf("unable to get sgid\n");
		return ret;
	}

	ret = get_pkey(ifr, pkey);
	if (ret) {
		printf("unable to get pkey\n");
		return ret;
	}

	for (*dev_index = 0; *dev_index < dev_cnt; (*dev_index)++) {
		ret = ibv_query_device(verbs[*dev_index], &dev_attr);
		if (ret)
			continue;

		for (*port = 1; *port <= dev_attr.phys_port_cnt; (*port)++) {
			ret = ibv_query_port(verbs[*dev_index], *port, &port_attr);
			if (ret)
				continue;

			for (i = 0; i < port_attr.gid_tbl_len; i++) {
				ret = ibv_query_gid(verbs[*dev_index], *port, i, &gid);
				if (ret || !gid.global.interface_id)
					break;

				if (!memcmp(sgid.raw, gid.raw, sizeof gid))
					return 0;
			}
		}
	}
	return -1;
}

int gen_addr_ip(FILE *f)
{
	struct ifconf *ifc;
	struct ifreq *ifr;
	char ip[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
	int s, ret, dev_index, i, len;
	uint16_t pkey;
	uint8_t port;

	s = socket(AF_INET6, SOCK_DGRAM, 0);
	if (!s)
		return -1;

	len = sizeof(*ifc) + sizeof(*ifr) * 64;
	ifc = malloc(len);
	if (!ifc) {
		ret = -1;
		goto out1;
	}

	memset(ifc, 0, len);
	ifc->ifc_len = len;
	ifc->ifc_req = (struct ifreq *) (ifc + 1);

	ret = ioctl(s, SIOCGIFCONF, ifc);
	if (ret < 0) {
		printf("ioctl ifconf error %d\n", ret);
		goto out2;
	}

	ifr = ifc->ifc_req;
	for (i = 0; i < ifc->ifc_len / sizeof(struct ifreq); i++) {
		switch (ifr[i].ifr_addr.sa_family) {
		case AF_INET:
			inet_ntop(ifr[i].ifr_addr.sa_family,
				&((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr, ip, sizeof ip);
			break;
		case AF_INET6:
			inet_ntop(ifr[i].ifr_addr.sa_family,
				&((struct sockaddr_in6 *) &ifr[i].ifr_addr)->sin6_addr, ip, sizeof ip);
			break;
		default:
			continue;
		}

		ret = ioctl(s, SIOCGIFHWADDR, &ifr[i]);
		if (ret) {
			printf("failed to get hw address %d\n", ret);
			continue;
		}

		if (ifr[i].ifr_hwaddr.sa_family != ARPHRD_INFINIBAND)
			continue;

		ret = get_devaddr(s, &ifr[i], &dev_index, &port, &pkey);
		if (ret)
			continue;

		printf("%s %s %d 0x%x\n", ip, verbs[dev_index]->device->name, port, pkey);
		fprintf(f, "%s %s %d 0x%x\n", ip, verbs[dev_index]->device->name, port, pkey);
	}
	ret = 0;

out2:
	free(ifc);
out1:
	close(s);
	return ret;
}


acme_windows.c - windows specific implementation to map IP addresses to
IB endpoints.  This code doesn't bother me so much.

/*
 * Copyright (c) 2009 Intel Corporation. All rights reserved.
 *
 * This software is available to you under the OpenIB.org BSD license
 * below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "..\..\..\..\etc\user\getopt.c"
#include "..\src\acme.c"
#include "..\..\..\..\etc\user\inet.c"
#include <rdma/winverbs.h>

extern struct ibv_context **verbs;
extern int dev_cnt;

int gen_addr_ip(FILE *f)
{
	WV_DEVICE_ADDRESS devaddr;
	IWVProvider *prov;
	HRESULT hr;
	struct addrinfo *res, hint, *ai;
	char ip[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
	int i;

	hr = WvGetObject(&IID_IWVProvider, (LPVOID *) &prov);
	if (FAILED(hr))
		return hr;

	memset(&hint, 0, sizeof hint);
	hint.ai_protocol = IPPROTO_TCP;

	hr = getaddrinfo("..localmachine", NULL, &hint, &res);
	if (hr) {
		printf("getaddrinfo error %d\n", hr);
		goto release;
	}

	for (ai = res; ai; ai = ai->ai_next) {
		switch (ai->ai_family) {
		case AF_INET:
			inet_ntop(ai->ai_family,
				&((struct sockaddr_in *) ai->ai_addr)->sin_addr, ip, sizeof ip);
			break;
		case AF_INET6:
			inet_ntop(ai->ai_family,
				&((struct sockaddr_in6 *) ai->ai_addr)->sin6_addr, ip, sizeof ip);
			break;
		default:
			continue;
		}

		hr = prov->lpVtbl->TranslateAddress(prov, ai->ai_addr, &devaddr);
		if (FAILED(hr))
			continue;

		for (i = 0; i < dev_cnt; i++) {
			if (devaddr.DeviceGuid == ibv_get_device_guid(verbs[i]->device)) {
				printf("%s %s %d 0x%x\n", ip, verbs[i]->device->name,
					devaddr.PortNumber, ntohs(devaddr.Pkey));
				fprintf(f, "%s %s %d 0x%x\n", ip, verbs[i]->device->name,
					devaddr.PortNumber, ntohs(devaddr.Pkey));
			}
		}
	}

	hr = 0;
	freeaddrinfo(res);
release:
	prov->lpVtbl->Release(prov);
	return hr;
}





More information about the general mailing list