[Pkg-ofed-commits] [ibacm] 03/11: Imported Upstream version 1.2.0

Ana Beatriz Guerrero López ana at moszumanska.debian.org
Tue Mar 29 22:24:11 UTC 2016


This is an automated email from the git hooks/post-receive script.

ana pushed a commit to branch master
in repository ibacm.

commit a70f1ea70c6aa97392c58d3a283f7a4fc7b17f2e
Author: Ana Beatriz Guerrero Lopez <ana at debian.org>
Date:   Tue Mar 29 16:27:33 2016 +0200

    Imported Upstream version 1.2.0
---
 Makefile.am          |   2 +-
 Makefile.in          |   2 +-
 config.h.in          |   3 +
 configure            |  40 +++--
 configure.ac         |   9 +-
 ibacm.spec           |   2 +-
 ibacm.spec.in        |   2 +-
 prov/acmp/src/acmp.c |  72 +++++++++
 src/acm.c            | 409 +++++++++++++++++++++++++++++++++++++++++++++++++--
 src/acm_netlink.h    | 128 ++++++++++++++++
 10 files changed, 644 insertions(+), 25 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 7690cb9..a910585 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -40,7 +40,7 @@ man_MANS = \
 EXTRA_DIST = src/acm_util.h prov/acmp/src/libibacmp.map \
 		include/acm_mad.h src/libacm.h ibacm.init.in \
 		linux/osd.h linux/dlist.h ibacm.spec.in \
-		$(man_MANS) ibacm_hosts.data
+		$(man_MANS) ibacm_hosts.data src/acm_netlink.h
 
 install-exec-hook:
 	install -D -m 755 ibacm.init $(DESTDIR)$(sysconfdir)/init.d/ibacm;
diff --git a/Makefile.in b/Makefile.in
index 389dffb..af96cb4 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -306,7 +306,7 @@ man_MANS = \
 EXTRA_DIST = src/acm_util.h prov/acmp/src/libibacmp.map \
 		include/acm_mad.h src/libacm.h ibacm.init.in \
 		linux/osd.h linux/dlist.h ibacm.spec.in \
-		$(man_MANS) ibacm_hosts.data
+		$(man_MANS) ibacm_hosts.data src/acm_netlink.h
 
 all: config.h
 	$(MAKE) $(AM_MAKEFLAGS) all-am
diff --git a/config.h.in b/config.h.in
index 283fa5c..eb9991d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -18,6 +18,9 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Have netlink header files */
+#undef HAVE_NETLINK
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
diff --git a/configure b/configure
index 7883c75..12fbe1f 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.67 for ibacm 1.1.0.
+# Generated by GNU Autoconf 2.67 for ibacm 1.2.0.
 #
 # Report bugs to <linux-rdma at vger.kernel.org>.
 #
@@ -701,8 +701,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='ibacm'
 PACKAGE_TARNAME='ibacm'
-PACKAGE_VERSION='1.1.0'
-PACKAGE_STRING='ibacm 1.1.0'
+PACKAGE_VERSION='1.2.0'
+PACKAGE_STRING='ibacm 1.2.0'
 PACKAGE_BUGREPORT='linux-rdma at vger.kernel.org'
 PACKAGE_URL=''
 
@@ -1427,7 +1427,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures ibacm 1.1.0 to adapt to many kinds of systems.
+\`configure' configures ibacm 1.2.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1497,7 +1497,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of ibacm 1.1.0:";;
+     short | recursive ) echo "Configuration of ibacm 1.2.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1601,7 +1601,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-ibacm configure 1.1.0
+ibacm configure 1.2.0
 generated by GNU Autoconf 2.67
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2148,7 +2148,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by ibacm $as_me 1.1.0, which was
+It was created by ibacm $as_me 1.2.0, which was
 generated by GNU Autoconf 2.67.  Invocation command line was
 
   $ $0 $@
@@ -2966,7 +2966,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='ibacm'
- VERSION='1.1.0'
+ VERSION='1.2.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -11656,6 +11656,26 @@ fi
 
 fi
 
+ac_fn_c_check_header_mongrel "$LINENO" "rdma/rdma_netlink.h" "ac_cv_header_rdma_rdma_netlink_h" "$ac_includes_default"
+if test "x$ac_cv_header_rdma_rdma_netlink_h" = x""yes; then :
+  ac_fn_c_check_header_mongrel "$LINENO" "rdma/ib_user_sa.h" "ac_cv_header_rdma_ib_user_sa_h" "$ac_includes_default"
+if test "x$ac_cv_header_rdma_ib_user_sa_h" = x""yes; then :
+
+$as_echo "#define HAVE_NETLINK 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Missing rdma/ib_user_sa.h" >&5
+$as_echo "$as_me: WARNING: Missing rdma/ib_user_sa.h" >&2;}
+fi
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Missing rdma/rdma_netlink.h" >&5
+$as_echo "$as_me: WARNING: Missing rdma/rdma_netlink.h" >&2;}
+fi
+
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler support for atomics" >&5
 $as_echo_n "checking compiler support for atomics... " >&6; }
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -12257,7 +12277,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by ibacm $as_me 1.1.0, which was
+This file was extended by ibacm $as_me 1.2.0, which was
 generated by GNU Autoconf 2.67.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -12323,7 +12343,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-ibacm config.status 1.1.0
+ibacm config.status 1.2.0
 configured by $0, generated by GNU Autoconf 2.67,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 4d493bd..226fb7f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.63])
-AC_INIT([ibacm], [1.1.0], [linux-rdma at vger.kernel.org])
+AC_INIT([ibacm], [1.2.0], [linux-rdma at vger.kernel.org])
 AC_CONFIG_SRCDIR([src/acm.c])
 AC_CONFIG_AUX_DIR(config)
 AC_CONFIG_HEADERS([config.h])
@@ -61,6 +61,13 @@ AC_CHECK_HEADER(infiniband/umad.h, [],
     AC_MSG_ERROR([<infiniband/umad.h> not found.  Is libibumad installed?]))
 fi
 
+dnl Check netlink header files
+AC_CHECK_HEADER(rdma/rdma_netlink.h,
+    AC_CHECK_HEADER(rdma/ib_user_sa.h,
+        AC_DEFINE(HAVE_NETLINK, 1, [Have netlink header files]),
+        AC_MSG_WARN([Missing rdma/ib_user_sa.h])),
+    AC_MSG_WARN([Missing rdma/rdma_netlink.h]))
+
 dnl Check for gcc atomic intrinsics
 AC_MSG_CHECKING(compiler support for atomics)
 AC_TRY_LINK([int i = 0;],
diff --git a/ibacm.spec b/ibacm.spec
index 0167e26..72ecc7e 100644
--- a/ibacm.spec
+++ b/ibacm.spec
@@ -1,5 +1,5 @@
 Name: ibacm
-Version: 1.1.0
+Version: 1.2.0
 Release: 1%{?dist}
 Summary: InfiniBand Communication Manager Assistant
 
diff --git a/ibacm.spec.in b/ibacm.spec.in
index 0167e26..72ecc7e 100644
--- a/ibacm.spec.in
+++ b/ibacm.spec.in
@@ -1,5 +1,5 @@
 Name: ibacm
-Version: 1.1.0
+Version: 1.2.0
 Release: 1%{?dist}
 Summary: InfiniBand Communication Manager Assistant
 
diff --git a/prov/acmp/src/acmp.c b/prov/acmp/src/acmp.c
index a590058..ec64631 100644
--- a/prov/acmp/src/acmp.c
+++ b/prov/acmp/src/acmp.c
@@ -46,15 +46,18 @@
 #include <infiniband/acm_prov.h>
 #include <infiniband/umad.h>
 #include <infiniband/verbs.h>
+#include <ifaddrs.h>
 #include <dlist.h>
 #include <dlfcn.h> 
 #include <search.h>
+#include <netdb.h>
 #include <net/if.h>
 #include <sys/ioctl.h>
 #include <net/if_arp.h>
 #include <netinet/in.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
+#include "acm_util.h"
 #include "acm_mad.h"
 
 #define src_out     data[0]
@@ -1739,6 +1742,74 @@ static int acmp_dest_timeout(struct acmp_dest *dest)
 }
 
 static int
+acmp_check_addr_match(struct ifaddrs *iap, struct acm_ep_addr_data *saddr,
+		      unsigned int d_family)
+{
+	char sip[INET6_ADDRSTRLEN] = {0};
+	char dip[INET6_ADDRSTRLEN] = {0};
+	const char *tmp;
+	size_t sock_size;
+	unsigned int s_family;
+	int ret;
+
+	s_family = iap->ifa_addr->sa_family;
+
+	if (!iap->ifa_addr ||
+	    !(iap->ifa_flags & IFF_UP) ||
+	    (s_family != d_family))
+		return -1;
+
+	sock_size = (s_family == AF_INET) ? sizeof(struct sockaddr_in) :
+		sizeof(struct sockaddr_in6);
+
+	ret = getnameinfo(iap->ifa_addr, sock_size,
+			  sip, sizeof(sip),
+			  NULL, 0, NI_NUMERICHOST);
+
+	if (ret)
+		return ret;
+
+	tmp = inet_ntop(d_family, (void *)saddr->info.addr, dip,
+			sizeof(dip));
+	if (!tmp)
+		return -1;
+	ret = memcmp(sip, dip, strlen(dip));
+	return ret;
+}
+
+static void
+acmp_acquire_sgid(struct acm_ep_addr_data *saddr,
+		  struct acmp_dest *dest)
+{
+	struct ifaddrs *addrs, *iap;
+	unsigned int d_family;
+	int ret;
+
+	if (!ib_any_gid(&dest->path.sgid))
+		return;
+
+	if (dest->addr_type != ACM_ADDRESS_IP6 &&
+	    dest->addr_type != ACM_ADDRESS_IP)
+		return;
+
+	if (getifaddrs(&addrs))
+		return;
+
+	d_family = (dest->addr_type == ACM_ADDRESS_IP) ? AF_INET : AF_INET6;
+
+	for (iap = addrs; iap != NULL; iap = iap->ifa_next) {
+		ret = acmp_check_addr_match(iap, saddr, d_family);
+		if (!ret) {
+			ret = acm_if_get_sgid(iap->ifa_name,
+					      &dest->path.sgid);
+			if (!ret)
+				break;
+		}
+	}
+	freeifaddrs(addrs);
+}
+
+static int
 acmp_resolve_dest(struct acmp_ep *ep, struct acm_msg *msg, uint64_t id)
 {
 	struct acmp_dest *dest;
@@ -1774,6 +1845,7 @@ test:
 		acm_log(2, "have address, resolving route\n");
 		acm_increment_counter(ACM_CNTR_ADDR_CACHE);
 		atomic_inc(&ep->counters[ACM_CNTR_ADDR_CACHE]);
+		acmp_acquire_sgid(saddr, dest);
 		status = acmp_resolve_path_sa(ep, dest, acmp_dest_sa_resp);
 		if (status) {
 			break;
diff --git a/src/acm.c b/src/acm.c
index 7649725..f6191bd 100644
--- a/src/acm.c
+++ b/src/acm.c
@@ -46,6 +46,10 @@
 #include <infiniband/acm_prov.h>
 #include <infiniband/umad.h>
 #include <infiniband/verbs.h>
+#ifdef HAVE_NETLINK
+#include <infiniband/umad_types.h>
+#include <infiniband/umad_sa.h>
+#endif
 #include <dlist.h>
 #include <dlfcn.h> 
 #include <search.h>
@@ -55,9 +59,18 @@
 #include <netinet/in.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
+#ifdef HAVE_NETLINK
+#include <rdma/rdma_netlink.h>
+#include <rdma/ib_user_sa.h>
+#endif
 #include <poll.h>
 #include "acm_mad.h"
 #include "acm_util.h"
+#ifdef HAVE_NETLINK
+#if !defined(RDMA_NL_LS_F_ERR)
+	#include "acm_netlink.h"
+#endif
+#endif
 
 #define src_out     data[0]
 #define src_index   data[1]
@@ -66,6 +79,9 @@
 #define MAX_EP_ADDR 4
 #define NL_MSG_BUF_SIZE 4096
 #define ACM_PROV_NAME_SIZE 64
+#ifdef HAVE_NETLINK
+#define NL_CLIENT_INDEX 0
+#endif
 
 struct acmc_subnet {
 	DLIST_ENTRY            entry;
@@ -106,7 +122,8 @@ struct acmc_port {
 	union ibv_gid       *gid_tbl;
 	uint16_t            lid;
 	uint16_t            lid_mask;
-	int                 default_pkey_index;
+	int                 sa_pkey_index;
+	uint16_t            def_acm_pkey;
 };
 
 struct acmc_device {
@@ -151,6 +168,23 @@ struct acmc_sa_req {
 	struct acm_sa_mad	mad;
 };
 
+#ifdef HAVE_NETLINK
+struct acm_nl_path {
+	struct nlattr			attr_hdr;
+	struct ib_path_rec_data		rec;
+};
+
+struct acm_nl_msg {
+	struct nlmsghdr				nlmsg_header;
+	union {
+		uint8_t				data[ACM_MSG_DATA_LENGTH];
+		struct rdma_ls_resolve_header	resolve_header;
+		struct nlattr			attr[0];
+		struct acm_nl_path		path[0];
+	};
+};
+#endif
+
 static char def_prov_name[ACM_PROV_NAME_SIZE] = "ibacmp";
 static DLIST_ENTRY provider_list;
 static struct acmc_prov *def_provider = NULL;
@@ -172,6 +206,9 @@ static struct acmc_ep *acm_find_ep(struct acmc_port *port, uint16_t pkey);
 static int acm_ep_insert_addr(struct acmc_ep *ep, const char *name, uint8_t *addr,
 			      size_t addr_len, uint8_t addr_type);
 static void acm_event_handler(struct acmc_device *dev);
+#ifdef HAVE_NETLINK
+static int acm_nl_send(SOCKET sock, struct acm_msg *msg);
+#endif
 
 static struct sa_data {
 	int		timeout;
@@ -466,7 +503,13 @@ int acm_resolve_response(uint64_t id, struct acm_msg *msg)
 		goto release;
 	}
 
-	ret = send(client->sock, (char *) msg, msg->hdr.length, 0);
+#ifdef HAVE_NETLINK
+	if (id == NL_CLIENT_INDEX)
+		ret = acm_nl_send(client->sock, msg);
+	else
+#endif
+		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
@@ -597,6 +640,10 @@ static void acm_svr_accept(void)
 	}
 
 	for (i = 0; i < FD_SETSIZE - 1; i++) {
+	#ifdef HAVE_NETLINK
+		if (i == NL_CLIENT_INDEX)
+			continue;
+	#endif
 		if (!atomic_get(&client_array[i].refcnt))
 			break;
 	}
@@ -1346,6 +1393,330 @@ static void acm_ipnl_handler(void)
 	}
 }
 
+#ifdef HAVE_NETLINK
+static int acm_nl_send(SOCKET sock, struct acm_msg *msg)
+{
+	struct sockaddr_nl dst_addr;
+	struct acm_nl_msg acmnlmsg;
+	struct acm_nl_msg *orig;
+	int ret;
+	int datalen;
+
+	orig = (struct acm_nl_msg *) msg->hdr.tid;
+
+	memset(&dst_addr, 0, sizeof(dst_addr));
+	dst_addr.nl_family = AF_NETLINK;
+	dst_addr.nl_groups = (1 << (RDMA_NL_GROUP_LS - 1));
+
+	memset(&acmnlmsg, 0, sizeof(acmnlmsg));
+	acmnlmsg.nlmsg_header.nlmsg_len = NLMSG_HDRLEN;
+	acmnlmsg.nlmsg_header.nlmsg_pid = getpid();
+	acmnlmsg.nlmsg_header.nlmsg_type = orig->nlmsg_header.nlmsg_type;
+	acmnlmsg.nlmsg_header.nlmsg_seq = orig->nlmsg_header.nlmsg_seq;
+
+	if (msg->hdr.status != ACM_STATUS_SUCCESS) {
+		acm_log(2, "acm status no success = %d\n", msg->hdr.status);
+		acmnlmsg.nlmsg_header.nlmsg_flags |= RDMA_NL_LS_F_ERR;
+	} else {
+		acm_log(2, "acm status success\n");
+		acmnlmsg.nlmsg_header.nlmsg_len +=
+			NLA_ALIGN(sizeof(struct acm_nl_path));
+		acmnlmsg.path[0].attr_hdr.nla_type = LS_NLA_TYPE_PATH_RECORD;
+		acmnlmsg.path[0].attr_hdr.nla_len = sizeof(struct acm_nl_path);
+		if (orig->resolve_header.path_use ==
+		    LS_RESOLVE_PATH_USE_UNIDIRECTIONAL)
+			acmnlmsg.path[0].rec.flags = IB_PATH_PRIMARY |
+				IB_PATH_OUTBOUND;
+		else
+			acmnlmsg.path[0].rec.flags = IB_PATH_PRIMARY |
+				IB_PATH_GMP | IB_PATH_BIDIRECTIONAL;
+		memcpy(acmnlmsg.path[0].rec.path_rec,
+		       &msg->resolve_data[0].info.path,
+		       sizeof(struct ibv_path_record));
+	}
+
+	datalen = NLMSG_ALIGN(acmnlmsg.nlmsg_header.nlmsg_len);
+	ret = sendto(sock, &acmnlmsg, datalen, 0,
+		     (const struct sockaddr *)&dst_addr,
+		     (socklen_t)sizeof(dst_addr));
+	if (ret != datalen) {
+		acm_log(0, "ERROR - sendto = %d errno = %d\n", ret, errno);
+		ret = -1;
+	} else {
+		ret = msg->hdr.length;
+	}
+
+	free(orig);
+
+	return ret;
+}
+
+#define NLA_LEN(nla)	((nla)->nla_len - NLA_HDRLEN)
+#define NLA_DATA(nla)	((char *)(nla) + NLA_HDRLEN)
+
+static int acm_nl_parse_path_attr(struct nlattr *attr,
+				   struct acm_ep_addr_data *data)
+{
+	struct ibv_path_record *path;
+	uint64_t  *sid;
+	struct rdma_nla_ls_gid *gid;
+	uint8_t *tcl;
+	uint16_t *pkey;
+	uint16_t *qos;
+	uint16_t val;
+	int ret = 0;
+
+#define IBV_PATH_RECORD_QOS_MASK 0xfff0
+
+	path = &data->info.path;
+	switch (attr->nla_type & RDMA_NLA_TYPE_MASK) {
+	case LS_NLA_TYPE_SERVICE_ID:
+		sid = (uint64_t *) NLA_DATA(attr);
+		if (NLA_LEN(attr) == sizeof(*sid)) {
+			acm_log(2, "service_id 0x%llx\n", *sid);
+			path->service_id = htonll(*sid);
+		} else {
+			ret = -1;
+		}
+		break;
+
+	case LS_NLA_TYPE_DGID:
+		gid = (struct rdma_nla_ls_gid *) NLA_DATA(attr);
+		if (NLA_LEN(attr) == sizeof(gid->gid)) {
+			acm_format_name(2, log_data, sizeof(log_data),
+					ACM_ADDRESS_GID, gid->gid,
+					sizeof(union ibv_gid));
+			acm_log(2, "path dgid %s\n", log_data);
+			memcpy(path->dgid.raw, gid->gid, sizeof(path->dgid));
+			data->flags |= ACM_EP_FLAG_DEST;
+		} else {
+			ret = -1;
+		}
+		break;
+
+	case LS_NLA_TYPE_SGID:
+		gid = (struct rdma_nla_ls_gid *) NLA_DATA(attr);
+		if (NLA_LEN(attr) == sizeof(gid->gid)) {
+			acm_format_name(2, log_data, sizeof(log_data),
+					ACM_ADDRESS_GID, gid->gid,
+					sizeof(union ibv_gid));
+			acm_log(2, "path sgid %s\n", log_data);
+			memcpy(path->sgid.raw, gid->gid, sizeof(path->sgid));
+			data->flags |= ACM_EP_FLAG_SOURCE;
+		} else {
+			ret = -1;
+		}
+		break;
+
+	case LS_NLA_TYPE_TCLASS:
+		tcl = (uint8_t *) NLA_DATA(attr);
+		if (NLA_LEN(attr) == sizeof(*tcl)) {
+			acm_log(2, "tclass 0x%x\n", *tcl);
+			path->tclass = *tcl;
+		} else {
+			ret = -1;
+		}
+		break;
+
+	case LS_NLA_TYPE_PKEY:
+		pkey = (uint16_t *) NLA_DATA(attr);
+		if (NLA_LEN(attr) == sizeof(*pkey)) {
+			acm_log(2, "pkey 0x%x\n", *pkey);
+			path->pkey = htons(*pkey);
+		} else {
+			ret = -1;
+		}
+		break;
+
+	case LS_NLA_TYPE_QOS_CLASS:
+		qos = (uint16_t *) NLA_DATA(attr);
+		if (NLA_LEN(attr) == sizeof(*qos)) {
+			acm_log(2, "qos_class 0x%x\n", *qos);
+			val = ntohs(path->qosclass_sl);
+			val &= ~IBV_PATH_RECORD_QOS_MASK;
+			val |= (*qos & IBV_PATH_RECORD_QOS_MASK);
+			path->qosclass_sl = htons(val);
+		} else {
+			ret = -1;
+		}
+		break;
+
+	default:
+		acm_log(1, "WARN: unknown attr %x\n", attr->nla_type);
+		/* We can not ignore a mandatory attribute */
+		if (attr->nla_type & RDMA_NLA_F_MANDATORY)
+			ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static void acm_nl_process_invalid_request(struct acmc_client *client,
+					   struct acm_nl_msg *acmnlmsg)
+{
+	struct acm_msg msg;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.hdr.opcode = ACM_OP_RESOLVE;
+	msg.hdr.version = ACM_VERSION;
+	msg.hdr.length = ACM_MSG_HDR_LENGTH;
+	msg.hdr.status = ACM_STATUS_EINVAL;
+	msg.hdr.tid = (uint64_t) acmnlmsg;
+
+	acm_nl_send(client->sock, &msg);
+}
+
+static void acm_nl_process_resolve(struct acmc_client *client,
+				   struct acm_nl_msg *acmnlmsg)
+{
+	struct acm_msg msg;
+	struct nlattr *attr;
+	int payload_len;
+	int resolve_hdr_len;
+	int rem;
+	int total_attr_len;
+	int status;
+	unsigned char *data;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.hdr.opcode = ACM_OP_RESOLVE;
+	msg.hdr.version = ACM_VERSION;
+	msg.hdr.length = ACM_MSG_HDR_LENGTH + ACM_MSG_EP_LENGTH;
+	msg.hdr.status = ACM_STATUS_SUCCESS;
+	msg.hdr.tid = (uint64_t) acmnlmsg;
+	msg.resolve_data[0].type = ACM_EP_INFO_PATH;
+
+	/* We support only one pathrecord */
+	acm_log(2, "path use 0x%x\n", acmnlmsg->resolve_header.path_use);
+	if (acmnlmsg->resolve_header.path_use ==
+	    LS_RESOLVE_PATH_USE_UNIDIRECTIONAL)
+		msg.resolve_data[0].info.path.reversible_numpath = 1;
+	else
+		msg.resolve_data[0].info.path.reversible_numpath =
+			IBV_PATH_RECORD_REVERSIBLE | 1;
+
+	data = (unsigned char *) &acmnlmsg->nlmsg_header + NLMSG_HDRLEN;
+	resolve_hdr_len = NLMSG_ALIGN(sizeof(struct rdma_ls_resolve_header));
+	attr = (struct nlattr *) (data + resolve_hdr_len);
+	payload_len = acmnlmsg->nlmsg_header.nlmsg_len - NLMSG_HDRLEN -
+		resolve_hdr_len;
+	rem = payload_len;
+	while (1) {
+		if (rem < (int) sizeof(*attr) ||
+		    attr->nla_len < sizeof(*attr) ||
+		    attr->nla_len > rem)
+			break;
+
+		status = acm_nl_parse_path_attr(attr, &msg.resolve_data[0]);
+		if (status) {
+			acm_nl_process_invalid_request(client, acmnlmsg);
+			return;
+		}
+
+		/* Next attribute */
+		total_attr_len = NLA_ALIGN(attr->nla_len);
+		rem -= total_attr_len;
+		attr = (struct nlattr *) ((char *) attr + total_attr_len);
+	}
+
+	atomic_inc(&counter[ACM_CNTR_RESOLVE]);
+	acm_svr_resolve(client, &msg);
+}
+
+static int acm_nl_is_valid_resolve_request(struct acm_nl_msg *acmnlmsg)
+{
+	int payload_len;
+
+	payload_len = acmnlmsg->nlmsg_header.nlmsg_len - NLMSG_HDRLEN;
+	if (payload_len < (sizeof(struct rdma_ls_resolve_header) +
+			   sizeof(struct nlattr)))
+		return 0;
+
+	return 1;
+}
+
+static void acm_nl_receive(struct acmc_client *client)
+{
+	struct acm_nl_msg *acmnlmsg;
+	int datalen = sizeof(*acmnlmsg);
+	int ret;
+	uint16_t client_inx, op;
+
+	acmnlmsg = calloc(1, sizeof(*acmnlmsg));
+	if (!acmnlmsg) {
+		acm_log(0, "Out of memory for recving nl msg.\n");
+		return;
+	}
+	ret = recv(client->sock, acmnlmsg, datalen, 0);
+	if (!NLMSG_OK(&acmnlmsg->nlmsg_header, ret)) {
+		acm_log(0, "Netlink receive error: %d.\n", ret);
+		goto rcv_cleanup;
+	}
+
+	acm_log(2, "nlmsg: len %d type 0x%x flags 0x%x seq %d pid %d\n",
+		acmnlmsg->nlmsg_header.nlmsg_len,
+		acmnlmsg->nlmsg_header.nlmsg_type,
+		acmnlmsg->nlmsg_header.nlmsg_flags,
+		acmnlmsg->nlmsg_header.nlmsg_seq,
+		acmnlmsg->nlmsg_header.nlmsg_pid);
+
+	/* Currently we handle only request from the local service client */
+	client_inx = RDMA_NL_GET_CLIENT(acmnlmsg->nlmsg_header.nlmsg_type);
+	op = RDMA_NL_GET_OP(acmnlmsg->nlmsg_header.nlmsg_type);
+	if (client_inx != RDMA_NL_LS)
+		goto rcv_cleanup;
+
+	switch (op) {
+	case RDMA_NL_LS_OP_RESOLVE:
+		if (acm_nl_is_valid_resolve_request(acmnlmsg))
+			acm_nl_process_resolve(client, acmnlmsg);
+		else
+			acm_nl_process_invalid_request(client, acmnlmsg);
+		break;
+	default:
+		/* Not supported*/
+		acm_log(1, "WARN - invalid opcode %x\n", op);
+		acm_nl_process_invalid_request(client, acmnlmsg);
+		break;
+	}
+
+	return;
+rcv_cleanup:
+	free(acmnlmsg);
+}
+
+static int acm_init_nl(void)
+{
+	struct sockaddr_nl src_addr;
+	int ret;
+	SOCKET nl_rcv_socket;
+
+	nl_rcv_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_RDMA);
+	if (nl_rcv_socket == INVALID_SOCKET) {
+		acm_log(0, "ERROR - unable to allocate netlink recv socket\n");
+		return socket_errno();
+	}
+
+	memset(&src_addr, 0, sizeof(src_addr));
+	src_addr.nl_family = AF_NETLINK;
+	src_addr.nl_pid = getpid();
+	src_addr.nl_groups = (1 << (RDMA_NL_GROUP_LS - 1));
+
+	ret = bind(nl_rcv_socket, (struct sockaddr *)&src_addr,
+		   sizeof(src_addr));
+	if (ret == SOCKET_ERROR) {
+		acm_log(0, "ERROR - unable to bind netlink socket\n");
+		close(nl_rcv_socket);
+		return socket_errno();
+	}
+
+	/* init nl client structure */
+	client_array[NL_CLIENT_INDEX].sock = nl_rcv_socket;
+	return 0;
+}
+#endif
+
 static void acm_server(void)
 {
 	fd_set readfds;
@@ -1360,12 +1731,16 @@ static void acm_server(void)
 		acm_log(0, "ERROR - server listen failed\n");
 		return;
 	}
+#ifdef HAVE_NETLINK
+	ret = acm_init_nl();
+	if (ret)
+		acm_log(1, "Warn - Netlink init failed\n");
+#endif
 
 	while (1) {
 		n = (int) listen_socket;
 		FD_ZERO(&readfds);
 		FD_SET(listen_socket, &readfds);
-
 		n = max(n, (int) ip_mon_socket);
 		FD_SET(ip_mon_socket, &readfds);
 
@@ -1399,7 +1774,12 @@ static void acm_server(void)
 			if (client_array[i].sock != INVALID_SOCKET &&
 				FD_ISSET(client_array[i].sock, &readfds)) {
 				acm_log(2, "receiving from client %d\n", i);
-				acm_svr_receive(&client_array[i]);
+			#ifdef HAVE_NETLINK
+				if (i == NL_CLIENT_INDEX)
+					acm_nl_receive(&client_array[i]);
+				else
+			#endif
+					acm_svr_receive(&client_array[i]);
 			}
 		}
 
@@ -1652,7 +2032,7 @@ static int acm_assign_ep_names(struct acmc_ep *ep)
 				continue;
 			}
 		} else {
-			pkey = 0xFFFF;
+			pkey = ep->port->def_acm_pkey;
 		}
 
 		if (!stricmp(dev_name, dev) &&
@@ -1846,6 +2226,7 @@ static void acm_port_up(struct acmc_port *port)
 	int i, ret;
 	struct acmc_prov_context *dev_ctx;
 	int index = -1;
+	uint16_t first_pkey = 0;
 
 	acm_log(1, "%s %d\n", port->dev->device.verbs->device->name, 
 		port->port.port_num);
@@ -1891,15 +2272,18 @@ static void acm_port_up(struct acmc_port *port)
 		goto err1;
 	}
 
-	/* Determine the default pkey first.
-	   Order of preference: 0xffff, 0x7fff, first pkey
-	*/
+	/* Determine the default pkey for SA access first.
+	 *     Order of preference: 0xffff, 0x7fff
+	 * Use the first pkey as the default pkey for parsing address file.
+	 */
 	for (i = 0; i < attr.pkey_tbl_len; i++) {
 		ret = ibv_query_pkey(port->dev->device.verbs, 
 				     port->port.port_num, i, &pkey);
 		if (ret)
 			continue;
 		pkey = ntohs(pkey);
+		if (i == 0)
+			first_pkey = pkey;
 		if (pkey == 0xffff) {
 			index = i;
 			break;
@@ -1908,7 +2292,8 @@ static void acm_port_up(struct acmc_port *port)
 			index = i;
 		}
 	}
-	port->default_pkey_index = index < 0 ? 0: index;
+	port->sa_pkey_index = index < 0 ? 0 : index;
+	port->def_acm_pkey = first_pkey;
 
 	for (i = 0; i < attr.pkey_tbl_len; i++) {
 		ret = ibv_query_pkey(port->dev->device.verbs, 
@@ -2418,7 +2803,7 @@ int acm_send_sa_mad(struct acm_sa_mad *mad)
 	mad->umad.addr.qkey = port->sa_addr.qkey;
 	mad->umad.addr.lid = htons(port->sa_addr.lid);
 	mad->umad.addr.sl = port->sa_addr.sl;
-	mad->umad.addr.pkey_index = req->ep->port->default_pkey_index;
+	mad->umad.addr.pkey_index = req->ep->port->sa_pkey_index;
 
 	lock_acquire(&port->lock);
 	if (port->sa_credits && DListEmpty(&port->sa_wait)) {
@@ -2756,6 +3141,10 @@ int CDECL_FUNC main(int argc, char **argv)
 	acm_server();
 
 	acm_log(0, "shutting down\n");
+#ifdef HAVE_NETLINK
+	if (client_array[NL_CLIENT_INDEX].sock != INVALID_SOCKET)
+		close(client_array[NL_CLIENT_INDEX].sock);
+#endif
 	acm_close_providers();
 	acm_stop_sa_handler();
 	umad_done();
diff --git a/src/acm_netlink.h b/src/acm_netlink.h
new file mode 100644
index 0000000..867ae8c
--- /dev/null
+++ b/src/acm_netlink.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under the OpenFabrics.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.
+ */
+
+#if !defined(ACM_NETLINK_H)
+#define ACM_NETLINK_H
+
+/*
+ * This header file basically copies the local service related defines and
+ * structures from the latest kernel include/uapi/rdma/rdma_netlink.h file
+ * so that ibacm can be built without the latest kernel patches.
+ */
+
+enum {
+	RDMA_NL_LS = 4,	/* RDMA Local Services */
+};
+
+enum {
+	RDMA_NL_GROUP_LS = 3,
+};
+
+/*
+ * Local service operations:
+ *   RESOLVE - The client requests the local service to resolve a path.
+ *   SET_TIMEOUT - The local service requests the client to set the timeout.
+ */
+enum {
+	RDMA_NL_LS_OP_RESOLVE = 0,
+	RDMA_NL_LS_OP_SET_TIMEOUT,
+	RDMA_NL_LS_NUM_OPS
+};
+
+/* Local service netlink message flags */
+#define RDMA_NL_LS_F_ERR	0x0100	/* Failed response */
+
+/*
+ * Local service resolve operation family header.
+ * The layout for the resolve operation:
+ *    nlmsg header
+ *    family header
+ *    attributes
+ */
+
+/*
+ * Local service path use:
+ * Specify how the path(s) will be used.
+ *   ALL - For connected CM operation (6 pathrecords)
+ *   UNIDIRECTIONAL - For unidirectional UD (1 pathrecord)
+ *   GMP - For miscellaneous GMP like operation (at least 1 reversible
+ *         pathrecord)
+ */
+enum {
+	LS_RESOLVE_PATH_USE_ALL = 0,
+	LS_RESOLVE_PATH_USE_UNIDIRECTIONAL,
+	LS_RESOLVE_PATH_USE_GMP,
+	LS_RESOLVE_PATH_USE_MAX
+};
+
+#define LS_DEVICE_NAME_MAX 64
+
+struct rdma_ls_resolve_header {
+	__u8 device_name[LS_DEVICE_NAME_MAX];
+	__u8 port_num;
+	__u8 path_use;
+};
+
+/* Local service attribute type */
+#define RDMA_NLA_F_MANDATORY	(1 << 13)
+#define RDMA_NLA_TYPE_MASK	(~(NLA_F_NESTED | NLA_F_NET_BYTEORDER | \
+				  RDMA_NLA_F_MANDATORY))
+
+/*
+ * Local service attributes:
+ *   Attr Name       Size                       Byte order
+ *   -----------------------------------------------------
+ *   PATH_RECORD     struct ib_path_rec_data
+ *   TIMEOUT         u32                        cpu
+ *   SERVICE_ID      u64                        cpu
+ *   DGID            u8[16]                     BE
+ *   SGID            u8[16]                     BE
+ *   TCLASS          u8
+ *   PKEY            u16                        cpu
+ *   QOS_CLASS       u16                        cpu
+ */
+enum {
+	LS_NLA_TYPE_UNSPEC = 0,
+	LS_NLA_TYPE_PATH_RECORD,
+	LS_NLA_TYPE_TIMEOUT,
+	LS_NLA_TYPE_SERVICE_ID,
+	LS_NLA_TYPE_DGID,
+	LS_NLA_TYPE_SGID,
+	LS_NLA_TYPE_TCLASS,
+	LS_NLA_TYPE_PKEY,
+	LS_NLA_TYPE_QOS_CLASS,
+	LS_NLA_TYPE_MAX
+};
+
+/* Local service DGID/SGID attribute: big endian */
+struct rdma_nla_ls_gid {
+	__u8		gid[16];
+};
+
+#endif /* ACM_NETLINK_H */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ofed/ibacm.git



More information about the Pkg-ofed-commits mailing list