Skip to content

Commit 1beb24a

Browse files
committed
issue: 4207451 Move from env params to config file
MVP: Move from env params to config file. This change introduces a new configuration file that will be used to configure the system. The configuration file is a JSON file that contains all the configuration parameters that were previously passed as environment variables. In the case of a failure to load the configuration file, the system will fall back to the old environment variables method. See HLD and LLD for more information. This patch also adds unit-tests for the new configuration system. Signed-off-by: Tomer Cabouly <[email protected]>
1 parent daa2a8e commit 1beb24a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+4732
-175
lines changed

.gitignore

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ Makefile.in
2121
Makefile
2222
aclocal.m4
2323
autom4te.cache/
24-
config.h
24+
json_descriptor.h
25+
/config.h
2526
config.h.in
2627
config.h.in~
2728
config.log
@@ -77,3 +78,6 @@ docs/man/xlio.7
7778
docs/man/xlio_stats.8
7879
docs/man/xliod.8
7980
tools/daemon/xliod
81+
82+
tests/unit_tests/unit_tests
83+
*.pyc

Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ uninstall-all: uninstall
3838
tests:
3939
$(MAKE)
4040
$(MAKE) -C tests/gtest
41+
$(MAKE) -C tests/unit_tests
4142
$(MAKE) -C tests/latency_test
4243
$(MAKE) -C tests/throughput_test
4344
$(MAKE) -C tests/pps_test

config/m4/json.m4

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#
2+
# SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES
3+
# Copyright (c) 2001-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4+
# SPDX-License-Identifier: GPL-2.0-oJSONy or BSD-3-Clause
5+
#
6+
# This software is available to you under a choice of one of two
7+
# licenses. You may choose to be licensed under the terms of the GNU
8+
# General Public License (GPL) Version 2, available from the file
9+
# COPYING in the main directory of this source tree, or the
10+
# BSD license below:
11+
#
12+
# Redistribution and use in source and binary forms, with or
13+
# without modification, are permitted provided that the following
14+
# conditions are met:
15+
#
16+
# - Redistributions of source code must retain the above
17+
# copyright notice, this list of conditions and the following
18+
# disclaimer.
19+
#
20+
# - Redistributions in binary form must reproduce the above
21+
# copyright notice, this list of conditions and the following
22+
# disclaimer in the documentation and/or other materials
23+
# provided with the distribution.
24+
#
25+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29+
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30+
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32+
# SOFTWARE.
33+
#
34+
35+
# json.m4 - Detect json-c package
36+
#
37+
38+
##########################
39+
# Checking json-c library
40+
#
41+
AC_DEFUN([CHECK_JSON_LIB],
42+
[
43+
PKG_CHECK_MODULES([JSON_C], [json-c])
44+
45+
AC_SUBST([LIBJSON_LIBS], "$LIBJSON_C_LIBS")
46+
AC_SUBST([LIBJSON_CFLAGS], "$LIBJSON_C_CFLAGS")
47+
48+
])

configure.ac

+3
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
8484
m4_include([config/m4/func.m4])
8585
m4_include([config/m4/opt.m4])
8686
m4_include([config/m4/verbs.m4])
87+
m4_include([config/m4/json.m4])
8788
m4_include([config/m4/dpcp.m4])
8889
m4_include([config/m4/nl.m4])
8990
m4_include([config/m4/prof.m4])
@@ -312,6 +313,7 @@ AC_CHECK_LIB([rt], [clock_gettime])
312313
AC_CHECK_LIB([pthread], [pthread_create])
313314

314315
CHECK_NL_LIB()
316+
CHECK_JSON_LIB()
315317

316318
dnl===-----------------------------------------------------------------------===
317319
dnl===
@@ -413,6 +415,7 @@ AC_CONFIG_FILES([
413415
src/state_machine/Makefile
414416
tests/Makefile
415417
tests/gtest/Makefile
418+
tests/unit_tests/Makefile
416419
tools/Makefile
417420
tools/daemon/Makefile
418421
docs/man/Makefile

src/core/Makefile.am

+20-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11

22
noinst_LTLIBRARIES = \
33
libconfig_parser.la
4-
libconfig_parser_la_SOURCES =
5-
BUILT_SOURCES =
64

75
AM_LFLAGS = -Plibxlio_yy
86
AM_YFLAGS = -plibxlio_yy -d
@@ -15,10 +13,8 @@ LEX_OUTPUT_ROOT=lex.libxlio_yy
1513
#
1614
#BUILT_SOURCES += config_scanner.c config_parser.h config_parser.c
1715
#libconfig_parser_la_SOURCES += util/config_scanner.l util/config_parser.y
18-
libconfig_parser_la_SOURCES += config_scanner.c config_parser.c
16+
libconfig_parser_la_SOURCES = config_scanner.c config_parser.c
1917

20-
21-
CLEANFILES = $(BUILT_SOURCES)
2218
dist-hook:
2319
cd $(distdir); rm -f $(BUILT_SOURCES)
2420

@@ -56,14 +52,24 @@ libxlio_la_LDFLAGS := $(XLIO_LTO) $(XLIO_PROFILE) -no-undefined \
5652
-version-number @PRJ_LIBRARY_MAJOR@:@PRJ_LIBRARY_MINOR@:@PRJ_LIBRARY_REVISION@
5753

5854
libxlio_la_LIBADD = \
59-
-lrt -ldl -lpthread $(LIBNL_LIBS) $(VERBS_LIBS) $(DPCP_LIBS) $(XLIO_GCOV) \
55+
-lrt -ldl -lpthread $(LIBNL_LIBS) $(VERBS_LIBS) $(DPCP_LIBS) $(XLIO_GCOV) $(JSON_C_LIBS) \
6056
$(top_builddir)/src/utils/libutils.la \
6157
$(top_builddir)/src/vlogger/libvlogger.la \
6258
$(top_builddir)/src/state_machine/libstate_machine.la \
6359
$(top_builddir)/src/stats/libstats.la \
6460
$(top_builddir)/src/core/netlink/libnetlink.la \
6561
$(top_builddir)/src/core/infra/libinfra.la \
6662
libconfig_parser.la
63+
64+
dist_noinst_DATA = config/descriptor_providers/json_descriptor.json
65+
66+
BUILT_SOURCES = config/descriptor_providers/json_descriptor.h
67+
68+
config/descriptor_providers/json_descriptor.h: config/descriptor_providers/json_descriptor.json
69+
xxd -i config/descriptor_providers/json_descriptor.json > $@
70+
71+
CLEANFILES = $(BUILT_SOURCES)
72+
6773

6874
libxlio_la_SOURCES := \
6975
dev/allocator.cpp \
@@ -169,6 +175,14 @@ libxlio_la_SOURCES := \
169175
util/agent.cpp \
170176
util/data_updater.cpp \
171177
\
178+
config/config_manager.cpp \
179+
config/loaders/inline_loader.cpp \
180+
config/loaders/json_loader.cpp \
181+
config/descriptors/parameter_descriptor.cpp \
182+
config/descriptors/config_descriptor.cpp \
183+
config/descriptor_providers/json_descriptor_provider.cpp \
184+
config/utils/json_parsing.cpp \
185+
\
172186
libxlio.c \
173187
main.cpp \
174188
\

src/core/config/config.h

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES
3+
* Copyright (c) 2001-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4+
* SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause
5+
*
6+
* This software is available to you under a choice of one of two
7+
* licenses. You may choose to be licensed under the terms of the GNU
8+
* General Public License (GPL) Version 2, available from the file
9+
* COPYING in the main directory of this source tree, or the
10+
* BSD license below:
11+
*
12+
* Redistribution and use in source and binary forms, with or
13+
* without modification, are permitted provided that the following
14+
* conditions are met:
15+
*
16+
* - Redistributions of source code must retain the above
17+
* copyright notice, this list of conditions and the following
18+
* disclaimer.
19+
*
20+
* - Redistributions in binary form must reproduce the above
21+
* copyright notice, this list of conditions and the following
22+
* disclaimer in the documentation and/or other materials
23+
* provided with the distribution.
24+
*
25+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32+
* SOFTWARE.
33+
*/
34+
35+
#pragma once
36+
#include <experimental/any>
37+
#include <string>
38+
#include <stdexcept>
39+
40+
class config {
41+
public:
42+
virtual ~config() noexcept = default;
43+
template <typename T> T get_value(const std::string &key) const
44+
{
45+
// Defer to a pure virtual function to retrieve the raw value.
46+
std::experimental::any raw_value = get_value_as_any(key);
47+
48+
// Attempt to cast to the requested type T.
49+
try {
50+
return std::experimental::any_cast<T>(raw_value);
51+
} catch (const std::experimental::bad_any_cast &e) {
52+
throw std::runtime_error("config::get_value - Bad any_cast for key: " + key + " - " +
53+
e.what());
54+
}
55+
}
56+
57+
protected:
58+
virtual std::experimental::any get_value_as_any(const std::string &key) const = 0;
59+
};

src/core/config/config_bundle.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES
3+
* Copyright (c) 2001-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4+
* SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause
5+
*
6+
* This software is available to you under a choice of one of two
7+
* licenses. You may choose to be licensed under the terms of the GNU
8+
* General Public License (GPL) Version 2, available from the file
9+
* COPYING in the main directory of this source tree, or the
10+
* BSD license below:
11+
*
12+
* Redistribution and use in source and binary forms, with or
13+
* without modification, are permitted provided that the following
14+
* conditions are met:
15+
*
16+
* - Redistributions of source code must retain the above
17+
* copyright notice, this list of conditions and the following
18+
* disclaimer.
19+
*
20+
* - Redistributions in binary form must reproduce the above
21+
* copyright notice, this list of conditions and the following
22+
* disclaimer in the documentation and/or other materials
23+
* provided with the distribution.
24+
*
25+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32+
* SOFTWARE.
33+
*/
34+
35+
#pragma once
36+
37+
#include "descriptors/config_descriptor.h"
38+
39+
struct config_bundle {
40+
std::map<std::string, std::experimental::any> m_config_data;
41+
config_descriptor m_config_descriptor;
42+
};

src/core/config/config_manager.cpp

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES
3+
* Copyright (c) 2001-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4+
* SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause
5+
*
6+
* This software is available to you under a choice of one of two
7+
* licenses. You may choose to be licensed under the terms of the GNU
8+
* General Public License (GPL) Version 2, available from the file
9+
* COPYING in the main directory of this source tree, or the
10+
* BSD license below:
11+
*
12+
* Redistribution and use in source and binary forms, with or
13+
* without modification, are permitted provided that the following
14+
* conditions are met:
15+
*
16+
* - Redistributions of source code must retain the above
17+
* copyright notice, this list of conditions and the following
18+
* disclaimer.
19+
*
20+
* - Redistributions in binary form must reproduce the above
21+
* copyright notice, this list of conditions and the following
22+
* disclaimer in the documentation and/or other materials
23+
* provided with the distribution.
24+
*
25+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32+
* SOFTWARE.
33+
*/
34+
35+
#include "config_manager.h"
36+
#include "loaders/inline_loader.h"
37+
#include "loaders/json_loader.h"
38+
#include "descriptor_providers/json_descriptor_provider.h"
39+
#include "core/util/xlio_exception.h"
40+
41+
#include <fstream>
42+
43+
config_manager::config_manager()
44+
{
45+
std::queue<std::unique_ptr<loader>> loaders;
46+
47+
const char *inline_env = std::getenv("XLIO_INLINE_CONFIG");
48+
if (inline_env) {
49+
loaders.push(std::make_unique<inline_loader>("XLIO_INLINE_CONFIG"));
50+
}
51+
52+
const char *custom_path = std::getenv("XLIO_CUSTOM_CONFIG_FILE");
53+
if (custom_path) {
54+
loaders.push(std::make_unique<json_loader>(custom_path));
55+
} else {
56+
loaders.push(std::make_unique<json_loader>("/etc/libxlio_config.json"));
57+
}
58+
59+
initialize_manager(std::move(loaders), std::make_unique<json_descriptor_provider>());
60+
}
61+
62+
void config_manager::initialize_manager(std::queue<std::unique_ptr<loader>> &&value_loaders,
63+
std::unique_ptr<descriptor_provider> descriptor_provider)
64+
{
65+
if (value_loaders.empty() || !descriptor_provider) {
66+
throw_xlio_exception("loader/descriptor_provider cannot be null");
67+
}
68+
69+
// 1) Load raw config data - first in queue means higher priority.
70+
std::map<std::string, std::experimental::any> aggregated_config_data;
71+
while (!value_loaders.empty()) {
72+
auto loaded_data = value_loaders.front()->load_all();
73+
aggregated_config_data.insert(loaded_data.begin(), loaded_data.end());
74+
75+
value_loaders.pop();
76+
}
77+
78+
m_config_bundle.m_config_data = std::move(aggregated_config_data);
79+
80+
// 2) Load or build the descriptor structure
81+
m_config_bundle.m_config_descriptor = descriptor_provider->load_descriptors();
82+
83+
// 3) Validate all settings on construction (fail fast if invalid)
84+
validate_config();
85+
}
86+
87+
config_manager::config_manager(std::queue<std::unique_ptr<loader>> &&value_loaders,
88+
std::unique_ptr<descriptor_provider> descriptor_provider)
89+
{
90+
initialize_manager(std::move(value_loaders), std::move(descriptor_provider));
91+
}
92+
93+
// Validate all config items against their descriptors & constraints.
94+
// A real application might do more elaborate error handling/logging.
95+
void config_manager::validate_config() const
96+
{
97+
// For each key-value in config_data, see if we have descriptor constraints
98+
for (auto const &kv : m_config_bundle.m_config_data) {
99+
const auto &key = kv.first;
100+
const auto &value = kv.second;
101+
102+
// Retrieve the descriptor (could be empty if not found)
103+
auto param_desc = m_config_bundle.m_config_descriptor.get_parameter(key);
104+
// If there's a specific type required, check constraints
105+
if (!param_desc.validate(value)) {
106+
// Throw an exception if validation fails
107+
throw_xlio_exception("Validation failed for key: " + key);
108+
}
109+
}
110+
}
111+
112+
std::experimental::any config_manager::get_value_as_any(const std::string &key) const
113+
{
114+
// Try to find the key in the loaded data
115+
auto it = m_config_bundle.m_config_data.find(key);
116+
if (it == m_config_bundle.m_config_data.end()) {
117+
// Not found in data. Fallback to descriptor's default.
118+
return m_config_bundle.m_config_descriptor.get_parameter(key).default_value();
119+
}
120+
121+
return (it->second);
122+
}

0 commit comments

Comments
 (0)