DPDK patches and discussions
 help / color / mirror / Atom feed
From: Adrien Mazarguil <adrien.mazarguil@6wind.com>
To: Shahaf Shuler <shahafs@mellanox.com>
Cc: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>,
	dev@dpdk.org, Marcelo Ricardo Leitner <mleitner@redhat.com>
Subject: [dpdk-dev] [PATCH v2 2/4] net/mlx4: spawn rdma-core dependency plug-in
Date: Fri, 26 Jan 2018 15:19:00 +0100	[thread overview]
Message-ID: <20180126141215.30395-3-adrien.mazarguil@6wind.com> (raw)
In-Reply-To: <20180126141215.30395-1-adrien.mazarguil@6wind.com>

When mlx4 is not compiled directly as an independent shared object (e.g.
CONFIG_RTE_BUILD_SHARED_LIB not enabled for performance reasons), DPDK
applications inherit its dependencies on libibverbs and libmlx4 through
rte.app.mk.

This is an issue both when DPDK is delivered as a binary package (Linux
distributions) and for end users because rdma-core then propagates as a
mandatory dependency for everything.

Application writers relying on binary DPDK packages are not necessarily
aware of this fact and may end up delivering packages with broken
dependencies.

This patch therefore introduces an intermediate internal plug-in
hard-linked with rdma-core (to preserve symbol versioning) loaded by the
PMD through dlopen(), so that a missing rdma-core does not cause unresolved
symbols, allowing applications to start normally.

Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 config/common_base        |  1 +
 doc/guides/nics/mlx4.rst  | 13 +++++++
 drivers/net/mlx4/Makefile | 41 ++++++++++++++++++++++
 drivers/net/mlx4/mlx4.c   | 80 ++++++++++++++++++++++++++++++++++++++++++
 mk/rte.app.mk             |  4 +++
 5 files changed, 139 insertions(+)

diff --git a/config/common_base b/config/common_base
index 170a38939..f29f9e3a0 100644
--- a/config/common_base
+++ b/config/common_base
@@ -298,6 +298,7 @@ CONFIG_RTE_LIBRTE_AVF_16BYTE_RX_DESC=n
 #
 CONFIG_RTE_LIBRTE_MLX4_PMD=n
 CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
+CONFIG_RTE_LIBRTE_MLX4_DLOPEN_DEPS=y
 CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8
 
 #
diff --git a/doc/guides/nics/mlx4.rst b/doc/guides/nics/mlx4.rst
index cab45dfe8..1bff400fb 100644
--- a/doc/guides/nics/mlx4.rst
+++ b/doc/guides/nics/mlx4.rst
@@ -86,6 +86,19 @@ These options can be modified in the ``.config`` file.
 
   Toggle compilation of librte_pmd_mlx4 itself.
 
+- ``CONFIG_RTE_LIBRTE_MLX4_DLOPEN_DEPS`` (default **y**)
+
+  Build PMD with additional code to make it loadable without hard
+  dependencies on **libibverbs** nor **libmlx4**, which may not be installed
+  on the target system.
+
+  In this mode, their presence is still required for it to run properly,
+  however their absence won't prevent a DPDK application from starting (with
+  ``CONFIG_RTE_BUILD_SHARED_LIB`` disabled) and they won't show up as
+  missing with ``ldd(1)``.
+
+  This option has no performance impact.
+
 - ``CONFIG_RTE_LIBRTE_MLX4_DEBUG`` (default **n**)
 
   Toggle debugging code and stricter compilation flags. Enabling this option
diff --git a/drivers/net/mlx4/Makefile b/drivers/net/mlx4/Makefile
index 1d33c38ed..4ff49a087 100644
--- a/drivers/net/mlx4/Makefile
+++ b/drivers/net/mlx4/Makefile
@@ -38,7 +38,11 @@ LIB = librte_pmd_mlx4.a
 SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4_flow.c
+ifeq ($(CONFIG_RTE_LIBRTE_MLX4_DLOPEN_DEPS),y)
+SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4_glue_lib.c
+else
 SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4_glue.c
+endif
 SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4_intr.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4_mr.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4_rxq.c
@@ -55,7 +59,12 @@ CFLAGS += -D_BSD_SOURCE
 CFLAGS += -D_DEFAULT_SOURCE
 CFLAGS += -D_XOPEN_SOURCE=600
 CFLAGS += $(WERROR_FLAGS)
+ifeq ($(CONFIG_RTE_LIBRTE_MLX4_DLOPEN_DEPS),y)
+CFLAGS_mlx4_glue.o += -fPIC
+LDLIBS += -ldl
+else
 LDLIBS += -libverbs -lmlx4
+endif
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs
 LDLIBS += -lrte_bus_pci
@@ -109,7 +118,39 @@ mlx4_autoconf.h: mlx4_autoconf.h.new
 
 $(SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD):.c=.o): mlx4_autoconf.h
 
+# Generate dependency plug-in for rdma-core when the PMD must not be linked
+# directly, so that applications do not inherit this dependency.
+
+ifeq ($(CONFIG_RTE_LIBRTE_MLX4_DLOPEN_DEPS),y)
+
+mlx4_glue_lib.c: mlx4_glue_lib.so
+	$Q printf '#include <stddef.h>\n' > $@
+	$Q printf '#include <stdint.h>\n\n' >> $@
+	$Q printf 'const uint8_t mlx4_glue_lib[][16] = {\n' >> $@
+	$Q od -vt x1 $< | \
+	sed -ne '/^[[:xdigit:]]\{1,\}/{' \
+		-e 's///;' \
+		-e '/^$$/d; ' \
+		-e 's/[[:space:]]*$$//;' \
+		-e 's/[[:space:]]\{1,\}/\\x/g;' \
+		-e 's/^/	"/;' \
+		-e 's/$$/",/;' \
+		-e 'p;' \
+		-e '}' >> $@
+	$Q printf '};\n\n' >> $@
+	$Q printf 'const size_t mlx4_glue_lib_size = %u;\n' \
+		$$(wc -c < $<) >> $@
+
+mlx4_glue_lib.so: mlx4_glue.o
+	$Q $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) \
+		-s -shared -o $@ $< -libverbs -lmlx4
+
+mlx4_glue.o: mlx4_autoconf.h
+
+endif
+
 clean_mlx4: FORCE
 	$Q rm -f -- mlx4_autoconf.h mlx4_autoconf.h.new
+	$Q rm -f -- mlx4_glue.o mlx4_glue_lib.*
 
 clean: clean_mlx4
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 0fd9a999c..979e29291 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -37,6 +37,7 @@
  */
 
 #include <assert.h>
+#include <dlfcn.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <stddef.h>
@@ -44,6 +45,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 /* Verbs headers do not support -pedantic. */
 #ifdef PEDANTIC
@@ -55,6 +57,7 @@
 #endif
 
 #include <rte_common.h>
+#include <rte_config.h>
 #include <rte_dev.h>
 #include <rte_errno.h>
 #include <rte_ethdev_driver.h>
@@ -724,6 +727,78 @@ static struct rte_pci_driver mlx4_driver = {
 		     RTE_PCI_DRV_INTR_RMV,
 };
 
+#ifdef RTE_LIBRTE_MLX4_DLOPEN_DEPS
+
+extern const uint8_t mlx4_glue_lib[][16];
+extern const size_t mlx4_glue_lib_size;
+
+/**
+ * Initialization routine for run-time dependency on rdma-core.
+ */
+static int
+mlx4_glue_init(void)
+{
+	char file[] = "/tmp/" MLX4_DRIVER_NAME "_XXXXXX";
+	int fd = mkstemp(file);
+	size_t off = 0;
+	void *handle = NULL;
+	void **sym;
+	const char *dlmsg;
+
+	if (fd == -1) {
+		rte_errno = errno;
+		goto glue_error;
+	}
+	while (off != mlx4_glue_lib_size) {
+		ssize_t ret;
+
+		ret = write(fd, (const uint8_t *)mlx4_glue_lib + off,
+			    mlx4_glue_lib_size - off);
+		if (ret == -1) {
+			if (errno != EINTR) {
+				rte_errno = errno;
+				goto glue_error;
+			}
+			ret = 0;
+		}
+		off += ret;
+	}
+	close(fd);
+	fd = -1;
+	handle = dlopen(file, RTLD_LAZY);
+	unlink(file);
+	if (!handle) {
+		rte_errno = EINVAL;
+		dlmsg = dlerror();
+		if (dlmsg)
+			ERROR("cannot load glue library: %s", dlmsg);
+		goto glue_error;
+	}
+	sym = dlsym(handle, "mlx4_glue");
+	if (!sym || !*sym) {
+		rte_errno = EINVAL;
+		dlmsg = dlerror();
+		if (dlmsg)
+			ERROR("cannot resolve glue symbol: %s", dlmsg);
+		goto glue_error;
+	}
+	mlx4_glue = *sym;
+	return 0;
+glue_error:
+	if (handle)
+		dlclose(handle);
+	if (fd != -1) {
+		close(fd);
+		unlink(file);
+	}
+	ERROR("cannot initialize PMD due to missing run-time"
+	      " dependency on rdma-core libraries (libibverbs,"
+	      " libmlx4)");
+	return -rte_errno;
+}
+
+#endif
+
 /**
  * Driver initialization routine.
  */
@@ -744,6 +819,11 @@ rte_mlx4_pmd_init(void)
 	 * using this PMD, which is not supported in forked processes.
 	 */
 	setenv("RDMAV_HUGEPAGES_SAFE", "1", 1);
+#ifdef RTE_LIBRTE_MLX4_DLOPEN_DEPS
+	if (mlx4_glue_init())
+		return;
+	assert(mlx4_glue);
+#endif
 	mlx4_glue->fork_init();
 	rte_pci_register(&mlx4_driver);
 }
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 0169f3f5b..fdbe36630 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -143,7 +143,11 @@ ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KNI)        += -lrte_pmd_kni
 endif
 _LDLIBS-$(CONFIG_RTE_LIBRTE_LIO_PMD)        += -lrte_pmd_lio
+ifeq ($(CONFIG_RTE_LIBRTE_MLX4_DLOPEN_DEPS),y)
+_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += -lrte_pmd_mlx4 -ldl
+else
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += -lrte_pmd_mlx4 -libverbs -lmlx4
+endif
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += -lrte_pmd_mlx5 -libverbs -lmlx5
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MRVL_PMD)       += -lrte_pmd_mrvl -L$(LIBMUSDK_PATH)/lib -lmusdk
 _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD)        += -lrte_pmd_nfp
-- 
2.11.0

  parent reply	other threads:[~2018-01-26 14:19 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-24 23:24 [dpdk-dev] [PATCH v1 0/4] net/mlx: make rdma-core optional at run-time Adrien Mazarguil
2018-01-24 23:25 ` [dpdk-dev] [PATCH v1 1/4] net/mlx4: move rdma-core calls to separate file Adrien Mazarguil
2018-01-24 23:58   ` Stephen Hemminger
2018-01-25 11:31     ` Adrien Mazarguil
2018-01-24 23:25 ` [dpdk-dev] [PATCH v1 2/4] net/mlx4: spawn rdma-core dependency plug-in Adrien Mazarguil
2018-01-26 10:06   ` Thomas Monjalon
2018-01-24 23:25 ` [dpdk-dev] [PATCH v1 3/4] net/mlx5: move rdma-core calls to separate file Adrien Mazarguil
2018-01-24 23:25 ` [dpdk-dev] [PATCH v1 4/4] net/mlx5: spawn rdma-core dependency plug-in Adrien Mazarguil
2018-01-26 14:18 ` [dpdk-dev] [PATCH v2 0/4] net/mlx: make rdma-core optional at run-time Adrien Mazarguil
2018-01-26 14:18   ` [dpdk-dev] [PATCH v2 1/4] net/mlx4: move rdma-core calls to separate file Adrien Mazarguil
2018-01-26 14:19   ` Adrien Mazarguil [this message]
2018-01-27 15:03     ` [dpdk-dev] [PATCH v2 2/4] net/mlx4: spawn rdma-core dependency plug-in Marcelo Ricardo Leitner
2018-01-28  9:04       ` Shahaf Shuler
2018-01-28 11:17         ` Marcelo Ricardo Leitner
2018-01-28 11:46           ` Shahaf Shuler
2018-01-26 14:19   ` [dpdk-dev] [PATCH v2 3/4] net/mlx5: move rdma-core calls to separate file Adrien Mazarguil
2018-01-26 14:19   ` [dpdk-dev] [PATCH v2 4/4] net/mlx5: spawn rdma-core dependency plug-in Adrien Mazarguil
2018-01-26 15:58   ` [dpdk-dev] [PATCH v2 0/4] net/mlx: make rdma-core optional at run-time Nélio Laranjeiro
2018-01-29 17:19   ` [dpdk-dev] [PATCH v3 " Adrien Mazarguil
2018-01-29 17:19     ` [dpdk-dev] [PATCH v3 1/4] net/mlx4: move rdma-core calls to separate file Adrien Mazarguil
2018-01-29 17:19     ` [dpdk-dev] [PATCH v3 2/4] net/mlx4: spawn rdma-core dependency plug-in Adrien Mazarguil
2018-01-29 17:19     ` [dpdk-dev] [PATCH v3 3/4] net/mlx5: move rdma-core calls to separate file Adrien Mazarguil
2018-01-29 17:19     ` [dpdk-dev] [PATCH v3 4/4] net/mlx5: spawn rdma-core dependency plug-in Adrien Mazarguil
2018-01-30 15:34     ` [dpdk-dev] [PATCH v4 0/4] net/mlx: make rdma-core optional at run-time Adrien Mazarguil
2018-01-30 15:34       ` [dpdk-dev] [PATCH v4 1/4] net/mlx4: move rdma-core calls to separate file Adrien Mazarguil
2018-01-30 15:34       ` [dpdk-dev] [PATCH v4 2/4] net/mlx4: spawn rdma-core dependency plug-in Adrien Mazarguil
2018-01-30 17:54         ` Marcelo Ricardo Leitner
2018-01-30 18:32           ` Adrien Mazarguil
2018-01-30 15:34       ` [dpdk-dev] [PATCH v4 3/4] net/mlx5: move rdma-core calls to separate file Adrien Mazarguil
2018-01-30 15:34       ` [dpdk-dev] [PATCH v4 4/4] net/mlx5: spawn rdma-core dependency plug-in Adrien Mazarguil
2018-01-31 10:13       ` [dpdk-dev] [PATCH v4 0/4] net/mlx: make rdma-core optional at run-time Shahaf Shuler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180126141215.30395-3-adrien.mazarguil@6wind.com \
    --to=adrien.mazarguil@6wind.com \
    --cc=dev@dpdk.org \
    --cc=mleitner@redhat.com \
    --cc=nelio.laranjeiro@6wind.com \
    --cc=shahafs@mellanox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).