[dpdk-dev] [PATCH v1 4/4] net/mlx5: spawn rdma-core dependency plug-in

Adrien Mazarguil adrien.mazarguil at 6wind.com
Thu Jan 25 00:25:06 CET 2018


When mlx5 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 libmlx5 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 at 6wind.com>
---
 drivers/net/mlx5/Makefile | 40 +++++++++++++++++++++
 drivers/net/mlx5/mlx5.c   | 79 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index bdec30692..35525f6d0 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -53,7 +53,11 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rss.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mr.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c
+ifneq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_glue_lib.c
+else
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_glue.c
+endif
 
 # Basic CFLAGS.
 CFLAGS += -O3
@@ -65,7 +69,12 @@ CFLAGS += -D_DEFAULT_SOURCE
 CFLAGS += -D_XOPEN_SOURCE=600
 CFLAGS += $(WERROR_FLAGS)
 CFLAGS += -Wno-strict-prototypes
+ifneq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+CFLAGS_mlx5_glue.o += -fPIC
+LDLIBS += -ldl
+else
 LDLIBS += -libverbs -lmlx5
+endif
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs
 LDLIBS += -lrte_bus_pci
@@ -158,7 +167,38 @@ mlx5_autoconf.h: mlx5_autoconf.h.new
 
 $(SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD):.c=.o): mlx5_autoconf.h
 
+# Generate dependency plug-in for rdma-core when the PMD cannot be linked
+# directly, so that applications do not inherit this dependency.
+
+ifneq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+
+mlx5_glue_lib.c: mlx5_glue_lib.so
+	$Q printf '#include <stddef.h>\n' > $@
+	$Q printf '#include <stdint.h>\n\n' >> $@
+	$Q printf 'const uint8_t mlx5_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 mlx5_glue_lib_size = %u;' $$(wc -c < $<) >> $@
+
+mlx5_glue_lib.so: mlx5_glue.o
+	$Q $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) \
+		-s -shared -o $@ $< -libverbs -lmlx5
+
+mlx5_glue.o: mlx5_autoconf.h
+
+endif
+
 clean_mlx5: FORCE
 	$Q rm -f -- mlx5_autoconf.h mlx5_autoconf.h.new
+	$Q rm -f -- mlx5_glue.o mlx5_glue_lib.*
 
 clean: clean_mlx5
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index b36cc611f..7ef724585 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -35,6 +35,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <assert.h>
+#include <dlfcn.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -56,6 +57,7 @@
 #include <rte_pci.h>
 #include <rte_bus_pci.h>
 #include <rte_common.h>
+#include <rte_config.h>
 #include <rte_kvargs.h>
 
 #include "mlx5.h"
@@ -966,6 +968,78 @@ static struct rte_pci_driver mlx5_driver = {
 	.drv_flags = RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_INTR_RMV,
 };
 
+#ifndef RTE_BUILD_SHARED_LIB
+
+extern const uint8_t mlx5_glue_lib[][16];
+extern const size_t mlx5_glue_lib_size;
+
+/**
+ * Initialization routine for run-time dependency on rdma-core.
+ */
+static int
+mlx5_glue_init(void)
+{
+	char file[] = "/tmp/" MLX5_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 != mlx5_glue_lib_size) {
+		ssize_t ret;
+
+		ret = write(fd, (const uint8_t *)mlx5_glue_lib + off,
+			    mlx5_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, "mlx5_glue");
+	if (!sym || !*sym) {
+		rte_errno = EINVAL;
+		dlmsg = dlerror();
+		if (dlmsg)
+			ERROR("cannot resolve glue symbol: %s", dlmsg);
+		goto glue_error;
+	}
+	mlx5_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,"
+	      " libmlx5)");
+	return -rte_errno;
+}
+
+#endif
+
 /**
  * Driver initialization routine.
  */
@@ -985,6 +1059,11 @@ rte_mlx5_pmd_init(void)
 	/* Match the size of Rx completion entry to the size of a cacheline. */
 	if (RTE_CACHE_LINE_SIZE == 128)
 		setenv("MLX5_CQE_SIZE", "128", 0);
+#ifndef RTE_BUILD_SHARED_LIB
+	if (mlx5_glue_init())
+		return;
+	assert(mlx5_glue);
+#endif
 	mlx5_glue->fork_init();
 	rte_pci_register(&mlx5_driver);
 }
-- 
2.11.0


More information about the dev mailing list