/*
 * Copyright (c) 2010-2012 Intel Corporation.  All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or 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 AND
 * 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 <config.h>

#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <unistd.h>

#include "cma.h"
#include "acm.h"
#include <rdma/rdma_cma.h>
#include <infiniband/ib.h>
#include <infiniband/sa.h>

static pthread_mutex_t acm_lock = PTHREAD_MUTEX_INITIALIZER;
static int sock = -1;
static uint16_t server_port;

static int ucma_set_server_port(void)
{
	FILE *f;

	if ((f = fopen(IBACM_PORT_FILE, "r" STREAM_CLOEXEC))) {
		if (fscanf(f, "%" SCNu16, &server_port) != 1)
			server_port = 0;
		fclose(f);
	} else
		server_port = 0;

	return server_port;
}

void ucma_ib_init(void)
{
	union {
		struct sockaddr any;
		struct sockaddr_in inet;
		struct sockaddr_un unx;
	} addr;
	static int init;
	int ret;

	if (init)
		return;

	pthread_mutex_lock(&acm_lock);
	if (init)
		goto unlock;

	if (ucma_set_server_port()) {
		sock = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
		if (sock < 0)
			goto out;

		memset(&addr, 0, sizeof(addr));
		addr.any.sa_family = AF_INET;
		addr.inet.sin_addr.s_addr = htobe32(INADDR_LOOPBACK);
		addr.inet.sin_port = htobe16(server_port);
		ret = connect(sock, &addr.any, sizeof(addr.inet));
		if (ret) {
			close(sock);
			sock = -1;
		}
	} else {
		sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
		if (sock < 0)
			goto out;

		memset(&addr, 0, sizeof(addr));
		addr.any.sa_family = AF_UNIX;
		BUILD_ASSERT(sizeof(IBACM_SERVER_PATH) <=
			     sizeof(addr.unx.sun_path));
		strcpy(addr.unx.sun_path, IBACM_SERVER_PATH);
		ret = connect(sock, &addr.any, sizeof(addr.unx));
		if (ret) {
			close(sock);
			sock = -1;
		}
	}
out:
	init = 1;
unlock:
	pthread_mutex_unlock(&acm_lock);
}

void ucma_ib_cleanup(void)
{
	if (sock >= 0) {
		shutdown(sock, SHUT_RDWR);
		close(sock);
	}
}

static int ucma_ib_set_addr(struct rdma_addrinfo *ib_rai,
			    struct rdma_addrinfo *rai)
{
	struct sockaddr_ib *src, *dst;
	struct ibv_path_record *path;

	src = calloc(1, sizeof(*src));
	if (!src)
		return ERR(ENOMEM);

	dst = calloc(1, sizeof(*dst));
	if (!dst) {
		free(src);
		return ERR(ENOMEM);
	}

	path = &((struct ibv_path_data *) ib_rai->ai_route)->path;

	src->sib_family = AF_IB;
	src->sib_pkey = path->pkey;
	src->sib_flowinfo = htobe32(be32toh(path->flowlabel_hoplimit) >> 8);
	memcpy(&src->sib_addr, &path->sgid, 16);
	ucma_set_sid(ib_rai->ai_port_space, rai->ai_src_addr, src);

	dst->sib_family = AF_IB;
	dst->sib_pkey = path->pkey;
	dst->sib_flowinfo = htobe32(be32toh(path->flowlabel_hoplimit) >> 8);
	memcpy(&dst->sib_addr, &path->dgid, 16);
	ucma_set_sid(ib_rai->ai_port_space, rai->ai_dst_addr, dst);

	ib_rai->ai_src_addr = (struct sockaddr *) src;
	ib_rai->ai_src_len = sizeof(*src);

	ib_rai->ai_dst_addr = (struct sockaddr *) dst;
	ib_rai->ai_dst_len = sizeof(*dst);

	return 0;
}
				 
static int ucma_ib_set_connect(struct rdma_addrinfo *ib_rai,
			       struct rdma_addrinfo *rai)
{
	struct ib_connect_hdr *hdr;

	if (rai->ai_family == AF_IB)
		return 0;

	hdr = calloc(1, sizeof(*hdr));
	if (!hdr)
		return ERR(ENOMEM);

	if (rai->ai_family == AF_INET) {
		hdr->ip_version = 4 << 4;
		memcpy(&hdr->cma_src_ip4,
		       &((struct sockaddr_in *) rai->ai_src_addr)->sin_addr, 4);
		memcpy(&hdr->cma_dst_ip4,
		       &((struct sockaddr_in *) rai->ai_dst_addr)->sin_addr, 4);
	} else {
		hdr->ip_version = 6 << 4;
		memcpy(&hdr->cma_src_ip6,
		       &((struct sockaddr_in6 *) rai->ai_src_addr)->sin6_addr, 16);
		memcpy(&hdr->cma_dst_ip6,
		       &((struct sockaddr_in6 *) rai->ai_dst_addr)->sin6_addr, 16);
	}

	ib_rai->ai_connect = hdr;
	ib_rai->ai_connect_len = sizeof(*hdr);
	return 0;
}

static void ucma_resolve_af_ib(struct rdma_addrinfo **rai)
{
	struct rdma_addrinfo *ib_rai;

	ib_rai = calloc(1, sizeof(*ib_rai));
	if (!ib_rai)
		return;

	ib_rai->ai_flags = (*rai)->ai_flags;
	ib_rai->ai_family = AF_IB;
	ib_rai->ai_qp_type = (*rai)->ai_qp_type;
	ib_rai->ai_port_space = (*rai)->ai_port_space;

	ib_rai->ai_route = calloc(1, (*rai)->ai_route_len);
	if (!ib_rai->ai_route)
		goto err;

	memcpy(ib_rai->ai_route, (*rai)->ai_route, (*rai)->ai_route_len);
	ib_rai->ai_route_len = (*rai)->ai_route_len;

	if ((*rai)->ai_src_canonname) {
		ib_rai->ai_src_canonname = strdup((*rai)->ai_src_canonname);
		if (!ib_rai->ai_src_canonname)
			goto err;
	}

	if ((*rai)->ai_dst_canonname) {
		ib_rai->ai_dst_canonname = strdup((*rai)->ai_dst_canonname);
		if (!ib_rai->ai_dst_canonname)
			goto err;
	}

	if (ucma_ib_set_connect(ib_rai, *rai))
		goto err;

	if (ucma_ib_set_addr(ib_rai, *rai))
		goto err;

	ib_rai->ai_next = *rai;
	*rai = ib_rai;
	return;

err:
	rdma_freeaddrinfo(ib_rai);
}

static void ucma_ib_save_resp(struct rdma_addrinfo *rai, struct acm_msg *msg)
{
	struct acm_ep_addr_data *ep_data;
	struct ibv_path_data *path_data = NULL;
	struct sockaddr_in *sin;
	struct sockaddr_in6 *sin6;
	int i, cnt, path_cnt = 0;

	cnt = (msg->hdr.length - ACM_MSG_HDR_LENGTH) / ACM_MSG_EP_LENGTH;
	for (i = 0; i < cnt; i++) {
		ep_data = &msg->resolve_data[i];
		switch (ep_data->type) {
		case ACM_EP_INFO_PATH:
			ep_data->type = 0;
			if (!path_data)
				path_data = (struct ibv_path_data *) ep_data;
			path_cnt++;
			break;
		case ACM_EP_INFO_ADDRESS_IP:
			if (!(ep_data->flags & ACM_EP_FLAG_SOURCE) || rai->ai_src_len)
				break;

			sin = calloc(1, sizeof(*sin));
			if (!sin)
				break;

			sin->sin_family = AF_INET;
			memcpy(&sin->sin_addr, &ep_data->info.addr, 4);
			rai->ai_src_len = sizeof(*sin);
			rai->ai_src_addr = (struct sockaddr *) sin;
			break;
		case ACM_EP_INFO_ADDRESS_IP6:
			if (!(ep_data->flags & ACM_EP_FLAG_SOURCE) || rai->ai_src_len)
				break;

			sin6 = calloc(1, sizeof(*sin6));
			if (!sin6)
				break;

			sin6->sin6_family = AF_INET6;
			memcpy(&sin6->sin6_addr, &ep_data->info.addr, 16);
			rai->ai_src_len = sizeof(*sin6);
			rai->ai_src_addr = (struct sockaddr *) sin6;
			break;
		default:
			break;
		}
	}

	rai->ai_route = calloc(path_cnt, sizeof(*path_data));
	if (rai->ai_route) {
		memcpy(rai->ai_route, path_data, path_cnt * sizeof(*path_data));
		rai->ai_route_len = path_cnt * sizeof(*path_data);
	}
}

static void ucma_set_ep_addr(struct acm_ep_addr_data *data, struct sockaddr *addr)
{
	if (addr->sa_family == AF_INET) {
		data->type = ACM_EP_INFO_ADDRESS_IP;
		memcpy(data->info.addr, &((struct sockaddr_in *) addr)->sin_addr, 4);
	} else {
		data->type = ACM_EP_INFO_ADDRESS_IP6;
		memcpy(data->info.addr, &((struct sockaddr_in6 *) addr)->sin6_addr, 16);
	}
}

static int ucma_inet_addr(struct sockaddr *addr, socklen_t len)
{
	return len && addr && (addr->sa_family == AF_INET ||
			       addr->sa_family == AF_INET6);
}

static int ucma_ib_addr(struct sockaddr *addr, socklen_t len)
{
	return len && addr && (addr->sa_family == AF_IB);
}

void ucma_ib_resolve(struct rdma_addrinfo **rai,
		     const struct rdma_addrinfo *hints)
{
	struct acm_msg msg;
	struct acm_ep_addr_data *data;
	int ret;

	ucma_ib_init();
	if (sock < 0)
		return;

	memset(&msg, 0, sizeof msg);
	msg.hdr.version = ACM_VERSION;
	msg.hdr.opcode = ACM_OP_RESOLVE;
	msg.hdr.length = ACM_MSG_HDR_LENGTH;

	data = &msg.resolve_data[0];
	if (ucma_inet_addr((*rai)->ai_src_addr, (*rai)->ai_src_len)) {
		data->flags = ACM_EP_FLAG_SOURCE;
		ucma_set_ep_addr(data, (*rai)->ai_src_addr);
		data++;
		msg.hdr.length += ACM_MSG_EP_LENGTH;
	}

	if (ucma_inet_addr((*rai)->ai_dst_addr, (*rai)->ai_dst_len)) {
		data->flags = ACM_EP_FLAG_DEST;
		if (hints->ai_flags & (RAI_NUMERICHOST | RAI_NOROUTE))
			data->flags |= ACM_FLAGS_NODELAY;
		ucma_set_ep_addr(data, (*rai)->ai_dst_addr);
		data++;
		msg.hdr.length += ACM_MSG_EP_LENGTH;
	}

	if (hints->ai_route_len ||
	    ucma_ib_addr((*rai)->ai_src_addr, (*rai)->ai_src_len) ||
	    ucma_ib_addr((*rai)->ai_dst_addr, (*rai)->ai_dst_len)) {
		struct ibv_path_record *path;

		if (hints->ai_route_len == sizeof(struct ibv_path_record))
			path = (struct ibv_path_record *) hints->ai_route;
		else if (hints->ai_route_len == sizeof(struct ibv_path_data))
			path = &((struct ibv_path_data *) hints->ai_route)->path;
		else
			path = NULL;

		if (path)
			memcpy(&data->info.path, path, sizeof(*path));

		if (ucma_ib_addr((*rai)->ai_src_addr, (*rai)->ai_src_len)) {
			memcpy(&data->info.path.sgid,
			       &((struct sockaddr_ib *) (*rai)->ai_src_addr)->sib_addr, 16);
		}
		if (ucma_ib_addr((*rai)->ai_dst_addr, (*rai)->ai_dst_len)) {
			memcpy(&data->info.path.dgid,
			       &((struct sockaddr_ib *) (*rai)->ai_dst_addr)->sib_addr, 16);
		}
		data->type = ACM_EP_INFO_PATH;
		data++;
		msg.hdr.length += ACM_MSG_EP_LENGTH;
	}

	pthread_mutex_lock(&acm_lock);
	ret = send(sock, (char *) &msg, msg.hdr.length, 0);
	if (ret != msg.hdr.length) {
		pthread_mutex_unlock(&acm_lock);
		return;
	}

	ret = recv(sock, (char *) &msg, sizeof msg, 0);
	pthread_mutex_unlock(&acm_lock);
	if (ret < ACM_MSG_HDR_LENGTH || ret != msg.hdr.length || msg.hdr.status)
		return;

	ucma_ib_save_resp(*rai, &msg);

	if (af_ib_support && !(hints->ai_flags & RAI_ROUTEONLY) && (*rai)->ai_route_len)
		ucma_resolve_af_ib(rai);
}
