[v1,1/1] linux-gen: add runtime configuration file

Message ID 1519416008-24422-2-git-send-email-odpbot@yandex.ru
State New
Headers show
Series
  • linux-gen: add runtime configuration file
Related show

Commit Message

Github ODP bot Feb. 23, 2018, 8 p.m.
From: Matias Elo <matias.elo@nokia.com>


Enables changing ODP runtime configuration options by using an optional
configuration file (libconfig). Path to the conf file is passed using
environment variable ODP_CONF_FILE. If ODP_CONF_FILE or a particular option
is not set, hardcoded default values are used intead. An example
configuration file is provided in config/odp-linux.conf.

Runtime configuration is initially used by DPDK pktio to set NIC options.

Adds new dependency to libconfig library.

Signed-off-by: Matias Elo <matias.elo@nokia.com>

---
/** Email created from pull request 499 (matiaselo:dev/dpdk_dev_config)
 ** https://github.com/Linaro/odp/pull/499
 ** Patch: https://github.com/Linaro/odp/pull/499.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: ab13bcecea3972b5af189e9e5d6d4873790fb554
 **/
 .travis.yml                                        |  3 +-
 DEPENDENCIES                                       |  2 +-
 config/README                                      |  8 +++
 config/odp-linux.conf                              | 20 +++++++
 m4/odp_libconfig.m4                                | 60 +++++++++++++++++++++
 platform/linux-generic/Makefile.am                 |  4 ++
 platform/linux-generic/include/odp_internal.h      |  4 ++
 .../linux-generic/include/odp_libconfig_internal.h | 29 ++++++++++
 platform/linux-generic/include/odp_packet_dpdk.h   |  8 +++
 platform/linux-generic/libodp-linux.pc.in          |  4 +-
 platform/linux-generic/m4/configure.m4             |  1 +
 platform/linux-generic/odp_init.c                  | 14 +++++
 platform/linux-generic/odp_libconfig.c             | 57 ++++++++++++++++++++
 platform/linux-generic/pktio/dpdk.c                | 63 ++++++++++++++++++++--
 platform/linux-generic/test/ring/Makefile.am       |  1 +
 15 files changed, 271 insertions(+), 7 deletions(-)
 create mode 100644 config/odp-linux.conf
 create mode 100644 m4/odp_libconfig.m4
 create mode 100644 platform/linux-generic/include/odp_libconfig_internal.h
 create mode 100644 platform/linux-generic/odp_libconfig.c

Patch

diff --git a/.travis.yml b/.travis.yml
index d9423adcc..4095516c9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,6 +21,7 @@  addons:
                         - gcc
                         - clang-3.8
                         - automake autoconf libtool libssl-dev graphviz mscgen
+                        - libconfig-dev
                         - codespell
                         - libpcap-dev
                         - libnuma-dev
@@ -254,7 +255,7 @@  script:
         - make -j $(nproc)
         - mkdir /dev/shm/odp
         - if [ -z "$CROSS_ARCH" ] ; then
-          sudo LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" ODP_SHM_DIR=/dev/shm/odp make check ;
+          sudo ODP_CONFIG_FILE="`pwd`/config/odp-linux.conf" LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" ODP_SHM_DIR=/dev/shm/odp make check ;
           fi
         - make install
 
diff --git a/DEPENDENCIES b/DEPENDENCIES
index 6f374ca92..b6765fecd 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -19,7 +19,7 @@  Prerequisites for building the OpenDataPlane (ODP) API
 
 3. Required libraries
 
-   Libraries currently required to link: openssl, libatomic
+   Libraries currently required to link: openssl, libatomic, libconfig
 
 3.1 OpenSSL native compile
 
diff --git a/config/README b/config/README
index 3f4336103..415334255 100644
--- a/config/README
+++ b/config/README
@@ -1,2 +1,10 @@ 
 ODP configuration options
 -------------------------
+
+Runtime configuration options can be passed to an ODP instance by
+setting ODP_CONFIG_FILE environment variable to point to a libconfig
+format configuration file. An example configuration file with default
+values is provided in config/odp-linux.conf. If ODP_CONFIG_FILE is not
+found, hardcoded default values are used instead of any configuration
+file. A configuration file doesn't have to include all available
+options. The missing options are replaced with hardcoded default values.
diff --git a/config/odp-linux.conf b/config/odp-linux.conf
new file mode 100644
index 000000000..eb40f5212
--- /dev/null
+++ b/config/odp-linux.conf
@@ -0,0 +1,20 @@ 
+# ODP runtime configuration options
+#
+# A configuration file doesn't have to include all available
+# options. The missing options are replaced with hardcoded default
+# values.
+#
+# See libconfig syntax: https://hyperrealm.github.io/libconfig/libconfig_manual.html#Configuration-Files
+
+# DPDK pktio options
+pktio_dpdk: {
+	# Default options
+	num_rx_desc = 128
+	num_tx_desc = 512
+	rx_drop_en = 0
+
+	# Driver specific options (use PMD names from DPDK)
+	net_ixgbe: {
+		rx_drop_en = 1
+	}
+}
diff --git a/m4/odp_libconfig.m4 b/m4/odp_libconfig.m4
new file mode 100644
index 000000000..e5b1d8acd
--- /dev/null
+++ b/m4/odp_libconfig.m4
@@ -0,0 +1,60 @@ 
+# ODP_LIBCONFIG([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -----------------------------------------------------
+AC_DEFUN([ODP_LIBCONFIG],
+[dnl
+AC_ARG_VAR([LIBCONFIG_CPPFLAGS], [C preprocessor flags for libconfig])
+AC_ARG_VAR([LIBCONFIG_LIBS], [linker flags for libconfig library])
+AC_ARG_VAR([LIBCONFIG_STATIC_LIBS], [static linker flags for libconfig library])
+
+##########################################################################
+# Set optional libconfig path
+##########################################################################
+AC_ARG_WITH([libconfig-path],
+[AS_HELP_STRING([--with-libconfig-path=DIR],
+	       [path to libconfig libs and headers (use system path if not provided)])],
+[LIBCONFIG_CPPFLAGS="-I$withval/include"
+LIBCONFIG_LIBS="-L$withval/lib -lconfig"],
+[if test "x$ac_cv_env_LIBCONFIG_LIBS_set" != "xset" ; then
+       LIBCONFIG_LIBS="-lconfig"
+fi])
+if test "x$ac_cv_env_LIBCONFIG_STATIC_LIBS_set" != "xset" ; then
+       LIBCONFIG_STATIC_LIBS="$LIBCONFIG_LIBS -ldl"
+fi
+
+##########################################################################
+# Save and set temporary compilation flags
+##########################################################################
+OLD_CPPFLAGS=$CPPFLAGS
+OLD_LIBS=$LIBS
+CPPFLAGS="$LIBCONFIG_CPPFLAGS $CPPFLAGS"
+LIBS="$LIBCONFIG_LIBS $LIBS"
+
+##########################################################################
+# Check for libconfig availability
+##########################################################################
+odp_libconfig_ok=yes
+AC_CHECK_HEADERS([libconfig.h], [],
+		 [odp_libconfig_ok=no])
+AC_CACHE_CHECK([for config_init in -lconfig], [odp_cv_libconfig],
+[AC_LINK_IFELSE([AC_LANG_CALL([], [config_init])],
+	       [odp_cv_libconfig=yes],
+	       [odp_cv_libconfig=no])])
+if test "x$odp_cv_libconfig" != "xyes" ; then
+	odp_libconfig_ok=no
+fi
+
+if test "x$odp_libconfig_ok" = "xyes" ; then
+	m4_default([$1], [:])
+else
+	LIBCONFIG_CPPFLAGS=""
+	LIBCONFIG_LIBS=""
+	LIBCONFIG_STATIC_LIBS=""
+	m4_default([$2], [AC_MSG_FAILURE([libconfig not found])])
+fi
+
+##########################################################################
+# Restore old saved variables
+##########################################################################
+LIBS=$OLD_LIBS
+CPPFLAGS=$OLD_CPPFLAGS
+]) # ODP_LIBCONFIG
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 7f212fe5e..b80719081 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -10,6 +10,7 @@  AM_CPPFLAGS +=  -I$(top_srcdir)/platform/$(with_platform)/arch/@ARCH_DIR@
 AM_CPPFLAGS +=  -I$(top_srcdir)/platform/$(with_platform)/arch/default
 
 AM_CPPFLAGS +=  $(OPENSSL_CPPFLAGS)
+AM_CPPFLAGS +=  $(LIBCONFIG_CPPFLAGS)
 AM_CPPFLAGS +=  $(DPDK_CPPFLAGS)
 AM_CPPFLAGS +=  $(NETMAP_CPPFLAGS)
 
@@ -94,6 +95,7 @@  noinst_HEADERS = \
 		  include/odp_forward_typedefs_internal.h \
 		  include/odp_internal.h \
 		  include/odp_ipsec_internal.h \
+		  include/odp_libconfig_internal.h \
 		  include/odp_llqueue.h \
 		  include/odp_macros_internal.h \
 		  include/odp_name_table_internal.h \
@@ -152,6 +154,7 @@  __LIB__libodp_linux_la_SOURCES = \
 			   odp_ipsec.c \
 			   odp_ipsec_events.c \
 			   odp_ipsec_sad.c \
+			   odp_libconfig.c \
 			   odp_name_table.c \
 			   odp_packet.c \
 			   odp_packet_flags.c \
@@ -284,6 +287,7 @@  endif
 
 __LIB__libodp_linux_la_LIBADD = $(ATOMIC_LIBS)
 __LIB__libodp_linux_la_LIBADD += $(OPENSSL_LIBS)
+__LIB__libodp_linux_la_LIBADD += $(LIBCONFIG_LIBS)
 __LIB__libodp_linux_la_LIBADD += $(DPDK_LIBS_LIBODP)
 __LIB__libodp_linux_la_LIBADD += $(PTHREAD_LIBS)
 __LIB__libodp_linux_la_LIBADD += $(TIMER_LIBS)
diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h
index f85a2f538..06ae54388 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -23,6 +23,7 @@  extern "C" {
 #include <odp_errno_define.h>
 #include <stdio.h>
 #include <sys/types.h>
+#include <libconfig.h>
 
 #define MAX_CPU_NUMBER 128
 #define UID_MAXLEN 30
@@ -55,10 +56,13 @@  struct odp_global_data_s {
 	odp_cpumask_t control_cpus;
 	odp_cpumask_t worker_cpus;
 	int num_cpus_installed;
+	config_t libconfig; /*< Runtime config using libconfig */
+	uint8_t libconfig_enabled; /*< Runtime config enabled */
 };
 
 enum init_stage {
 	NO_INIT = 0,    /* No init stages completed */
+	LIBCONFIG_INIT,
 	CPUMASK_INIT,
 	TIME_INIT,
 	SYSINFO_INIT,
diff --git a/platform/linux-generic/include/odp_libconfig_internal.h b/platform/linux-generic/include/odp_libconfig_internal.h
new file mode 100644
index 000000000..b75736d77
--- /dev/null
+++ b/platform/linux-generic/include/odp_libconfig_internal.h
@@ -0,0 +1,29 @@ 
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * Common libconfig functions
+ */
+
+#ifndef ODP_LIBCONFIG_INTERNAL_H_
+#define ODP_LIBCONFIG_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _odp_libconfig_init_global(void);
+int _odp_libconfig_term_global(void);
+
+config_setting_t *_odp_libconfig_lookup(const char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp_packet_dpdk.h b/platform/linux-generic/include/odp_packet_dpdk.h
index ec60b872f..5db7025e6 100644
--- a/platform/linux-generic/include/odp_packet_dpdk.h
+++ b/platform/linux-generic/include/odp_packet_dpdk.h
@@ -33,6 +33,13 @@  ODP_STATIC_ASSERT((DPDK_NB_MBUF % DPDK_MEMPOOL_CACHE_SIZE == 0) &&
 /* Minimum RX burst size */
 #define DPDK_MIN_RX_BURST 4
 
+/** DPDK runtime configuration options */
+typedef struct {
+	int num_rx_desc;
+	int num_tx_desc;
+	int rx_drop_en;
+} dpdk_opt_t;
+
 /** Cache for storing packets */
 struct pkt_cache_t {
 	/** array for storing extra RX packets */
@@ -64,6 +71,7 @@  typedef struct ODP_ALIGNED_CACHE {
 	odp_ticketlock_t tx_lock[PKTIO_MAX_QUEUES];  /**< TX queue locks */
 	/** cache for storing extra RX packets */
 	pkt_cache_t rx_cache[PKTIO_MAX_QUEUES];
+	dpdk_opt_t opt;
 } pkt_dpdk_t;
 
 #endif
diff --git a/platform/linux-generic/libodp-linux.pc.in b/platform/linux-generic/libodp-linux.pc.in
index 5125f83ad..0ab0e72c2 100644
--- a/platform/linux-generic/libodp-linux.pc.in
+++ b/platform/linux-generic/libodp-linux.pc.in
@@ -7,5 +7,5 @@  Name: libodp-linux
 Description: The ODP packet processing engine
 Version: @PKGCONFIG_VERSION@
 Libs: -L${libdir} -lodp-linux
-Libs.private: @OPENSSL_STATIC_LIBS@ @DPDK_LIBS@ @PCAP_LIBS@ @PTHREAD_LIBS@ @TIMER_LIBS@ -lpthread @ATOMIC_LIBS@
-Cflags: -I${includedir}
+Libs.private: @OPENSSL_STATIC_LIBS@ @LIBCONFIG_STATIC_LIBS@ @DPDK_LIBS@ @PCAP_LIBS@ @PTHREAD_LIBS@ @TIMER_LIBS@ -lpthread @ATOMIC_LIBS@
+Cflags: -I${includedir} @LIBCONFIG_CPPFLAGS@
diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4
index 935894b8c..a2fd1134f 100644
--- a/platform/linux-generic/m4/configure.m4
+++ b/platform/linux-generic/m4/configure.m4
@@ -6,6 +6,7 @@  ODP_ATOMIC
 ODP_PTHREAD
 ODP_TIMER
 ODP_OPENSSL
+ODP_LIBCONFIG
 m4_include([platform/linux-generic/m4/odp_pcap.m4])
 m4_include([platform/linux-generic/m4/odp_netmap.m4])
 m4_include([platform/linux-generic/m4/odp_dpdk.m4])
diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c
index 0c5adf335..fbfeb096b 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -12,6 +12,7 @@ 
 #include <unistd.h>
 #include <odp_internal.h>
 #include <odp_schedule_if.h>
+#include <odp_libconfig_internal.h>
 #include <string.h>
 #include <stdio.h>
 #include <linux/limits.h>
@@ -48,6 +49,12 @@  int odp_init_global(odp_instance_t *instance,
 			odp_global_data.abort_fn = params->abort_fn;
 	}
 
+	if (_odp_libconfig_init_global()) {
+		ODP_ERR("ODP runtime config init failed.\n");
+		goto init_failed;
+	}
+	stage = LIBCONFIG_INIT;
+
 	if (odp_cpumask_init_global(params)) {
 		ODP_ERR("ODP cpumask init failed.\n");
 		goto init_failed;
@@ -293,6 +300,13 @@  int _odp_term_global(enum init_stage stage)
 		}
 		/* Fall through */
 
+	case LIBCONFIG_INIT:
+		if (_odp_libconfig_term_global()) {
+			ODP_ERR("ODP runtime config term failed.\n");
+			rc = -1;
+		}
+		/* Fall through */
+
 	case NO_INIT:
 		;
 	}
diff --git a/platform/linux-generic/odp_libconfig.c b/platform/linux-generic/odp_libconfig.c
new file mode 100644
index 000000000..f52ca260e
--- /dev/null
+++ b/platform/linux-generic/odp_libconfig.c
@@ -0,0 +1,57 @@ 
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <libconfig.h>
+
+#include <odp_internal.h>
+#include <odp_debug_internal.h>
+#include <odp_libconfig_internal.h>
+
+extern struct odp_global_data_s odp_global_data;
+
+int _odp_libconfig_init_global(void)
+{
+	char *filename;
+	config_t *config = &odp_global_data.libconfig;
+
+	filename = getenv("ODP_CONFIG_FILE");
+	if (filename == NULL)
+		return 0;
+
+	config_init(config);
+
+	if (!config_read_file(config, filename)) {
+		ODP_ERR("Failed to read config file: %s(%d): %s\n",
+			config_error_file(config), config_error_line(config),
+			config_error_text(config));
+		config_destroy(config);
+		return -1;
+	}
+
+	odp_global_data.libconfig_enabled = 1;
+
+	return 0;
+}
+
+int _odp_libconfig_term_global(void)
+{
+	if (odp_global_data.libconfig_enabled)
+		config_destroy(&odp_global_data.libconfig);
+	return 0;
+}
+
+config_setting_t *_odp_libconfig_lookup(const char *path)
+{
+	config_t *config = &odp_global_data.libconfig;
+
+	if (!odp_global_data.libconfig_enabled)
+		return NULL;
+
+	return config_lookup(config, path);
+}
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c
index 6dc602389..e1d173ee6 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -14,6 +14,7 @@ 
 #include <ctype.h>
 #include <unistd.h>
 #include <math.h>
+#include <libconfig.h>
 
 #include <odp/api/cpumask.h>
 
@@ -24,6 +25,7 @@ 
 #include <odp_classification_internal.h>
 #include <odp_packet_dpdk.h>
 #include <odp_debug_internal.h>
+#include <odp_libconfig_internal.h>
 
 #include <protocols/eth.h>
 
@@ -93,6 +95,56 @@  void refer_constructors(void)
 }
 #endif
 
+static void lookup_opt(config_setting_t *default_opt, config_setting_t *drv_opt,
+		       const char *opt, int *val)
+{
+	/* Default option */
+	config_setting_lookup_int(default_opt, opt, val);
+
+	/* Driver option overwrites default option */
+	if (drv_opt)
+		config_setting_lookup_int(drv_opt, opt, val);
+}
+
+static void init_options(pktio_entry_t *pktio_entry,
+			 const struct rte_eth_dev_info *dev_info)
+{
+	dpdk_opt_t *opt = &pktio_entry->s.pkt_dpdk.opt;
+	config_setting_t *default_opt;
+	config_setting_t *drv_opt;
+
+	/* Default values. Update 'config/odp-linux.conf' if modified. */
+	opt->num_rx_desc = DPDK_NM_RX_DESC;
+	opt->num_tx_desc = DPDK_NM_TX_DESC;
+	opt->rx_drop_en = 0;
+
+	default_opt = _odp_libconfig_lookup("pktio_dpdk");
+	if (!default_opt) {
+		ODP_DBG("No DPDK pktio options found\n");
+		goto done;
+	}
+
+	/* config_lookup_from() was renamed to config_setting_lookup() in
+	 * libconfig 1.5.0 */
+#if (LIBCONFIG_VER_MAJOR <= 1 && LIBCONFIG_VER_MINOR < 5)
+	drv_opt = config_lookup_from(default_opt, dev_info->driver_name);
+#else
+	drv_opt = config_setting_lookup(default_opt, dev_info->driver_name);
+#endif
+
+	/* Read options from config file */
+	lookup_opt(default_opt, drv_opt, "num_rx_desc", &opt->num_rx_desc);
+	lookup_opt(default_opt, drv_opt, "num_tx_desc", &opt->num_tx_desc);
+	lookup_opt(default_opt, drv_opt, "rx_drop_en", &opt->rx_drop_en);
+
+done:
+	printf("DPDK interface (%s): %" PRIu16 "\n", dev_info->driver_name,
+	       pktio_entry->s.pkt_dpdk.port_id);
+	printf("  num_rx_desc: %d\n", opt->num_rx_desc);
+	printf("  num_tx_desc: %d\n", opt->num_tx_desc);
+	printf("  rx_drop_en: %d\n", opt->rx_drop_en);
+}
+
 /**
  * Calculate valid cache size for DPDK packet pool
  */
@@ -1337,6 +1389,9 @@  static int dpdk_open(odp_pktio_t id ODP_UNUSED,
 
 	dpdk_init_capability(pktio_entry, &dev_info);
 
+	/* Initialize runtime options */
+	init_options(pktio_entry, &dev_info);
+
 	mtu = dpdk_mtu_get(pktio_entry);
 	if (mtu == 0) {
 		ODP_ERR("Failed to read interface MTU\n");
@@ -1464,7 +1519,8 @@  static int dpdk_start(pktio_entry_t *pktio_entry)
 			pktio_entry->s.chksum_insert_ena = 1;
 		}
 
-		ret = rte_eth_tx_queue_setup(port_id, i, DPDK_NM_TX_DESC,
+		ret = rte_eth_tx_queue_setup(port_id, i,
+					     pkt_dpdk->opt.num_tx_desc,
 					     rte_eth_dev_socket_id(port_id),
 					     txconf);
 		if (ret < 0) {
@@ -1476,9 +1532,10 @@  static int dpdk_start(pktio_entry_t *pktio_entry)
 	/* Init RX queues */
 	rte_eth_dev_info_get(port_id, &dev_info);
 	rxconf = &dev_info.default_rxconf;
-	rxconf->rx_drop_en = 1;
+	rxconf->rx_drop_en = pkt_dpdk->opt.rx_drop_en;
 	for (i = 0; i < pktio_entry->s.num_in_queue; i++) {
-		ret = rte_eth_rx_queue_setup(port_id, i, DPDK_NM_RX_DESC,
+		ret = rte_eth_rx_queue_setup(port_id, i,
+					     pkt_dpdk->opt.num_rx_desc,
 					     rte_eth_dev_socket_id(port_id),
 					     rxconf, pkt_dpdk->pkt_pool);
 		if (ret < 0) {
diff --git a/platform/linux-generic/test/ring/Makefile.am b/platform/linux-generic/test/ring/Makefile.am
index 3f774342e..61c97e62e 100644
--- a/platform/linux-generic/test/ring/Makefile.am
+++ b/platform/linux-generic/test/ring/Makefile.am
@@ -15,6 +15,7 @@  TESTS = ring_main$(EXEEXT)
 PRELDADD += $(LIBCUNIT_COMMON)
 
 AM_CPPFLAGS += -I$(top_srcdir)/platform/linux-generic/include
+AM_CPPFLAGS += $(LIBCONFIG_CPPFLAGS)
 
 TESTNAME = linux-generic-ring