merge: branch 'nbft-parser-1'
initrd: add new NBFT parser https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2077
This commit is contained in:
@@ -60,11 +60,11 @@ variables:
|
||||
#
|
||||
# This is done by running `ci-fairy generate-template` and possibly bumping
|
||||
# ".default_tag".
|
||||
ALPINE_TAG: 'tag-77ec3d923fd6'
|
||||
CENTOS_TAG: 'tag-7a677f4838e1'
|
||||
DEBIAN_TAG: 'tag-ecad19904683'
|
||||
FEDORA_TAG: 'tag-7a677f4838e1'
|
||||
UBUNTU_TAG: 'tag-ecad19904683'
|
||||
ALPINE_TAG: 'tag-57edf560bf4f'
|
||||
CENTOS_TAG: 'tag-7ea4f50c8578'
|
||||
DEBIAN_TAG: 'tag-1601ce2572c5'
|
||||
FEDORA_TAG: 'tag-7ea4f50c8578'
|
||||
UBUNTU_TAG: 'tag-1601ce2572c5'
|
||||
|
||||
ALPINE_EXEC: 'bash .gitlab-ci/alpine-install.sh'
|
||||
CENTOS_EXEC: 'bash .gitlab-ci/fedora-install.sh'
|
||||
|
@@ -280,3 +280,8 @@
|
||||
/* Define to 1 if you have history support from -lreadline. */
|
||||
#mesondefine HAVE_READLINE_HISTORY
|
||||
|
||||
/* Define if NBFT support is enabled */
|
||||
#mesondefine WITH_NBFT
|
||||
|
||||
/* Define to 1 if dlvsym() is available */
|
||||
#mesondefine HAVE_DLVSYM
|
||||
|
@@ -24,6 +24,7 @@ apk add \
|
||||
'jansson-dev' \
|
||||
'libgudev-dev' \
|
||||
'libndp-dev' \
|
||||
'libnvme-dev' \
|
||||
'libnl3-dev' \
|
||||
'libpsl-dev' \
|
||||
'libsoup-dev' \
|
||||
|
@@ -56,6 +56,7 @@ install \
|
||||
libndp-dev \
|
||||
libnewt-dev \
|
||||
libnss3-dev \
|
||||
libnvme-dev \
|
||||
libpolkit-gobject-1-dev \
|
||||
libpsl-dev \
|
||||
libreadline-dev \
|
||||
|
@@ -66,6 +66,7 @@ install \
|
||||
jq \
|
||||
libcurl-devel \
|
||||
libndp-devel \
|
||||
libnvme-devel \
|
||||
libselinux-devel \
|
||||
libtool \
|
||||
libuuid-devel \
|
||||
|
@@ -307,6 +307,7 @@ BuildRequires: libubsan
|
||||
BuildRequires: firewalld-filesystem
|
||||
BuildRequires: iproute
|
||||
BuildRequires: iproute-tc
|
||||
BuildRequires: libnvme-devel >= 1.5
|
||||
|
||||
Provides: %{name}-dispatcher%{?_isa} = %{epoch}:%{version}-%{release}
|
||||
|
||||
|
@@ -54,10 +54,15 @@ _WITH_WERROR=1
|
||||
_WITH_LIBTEAM="true"
|
||||
_WITH_DOCS="true"
|
||||
_WITH_SYSTEMD_LOGIND="true"
|
||||
_WITH_NBFT="true"
|
||||
if [ $IS_ALPINE = 1 ]; then
|
||||
_WITH_SYSTEMD_LOGIND="false"
|
||||
fi
|
||||
|
||||
if ! pkgconf 'libnvme >= 1.5'; then
|
||||
_WITH_NBFT="false"
|
||||
fi
|
||||
|
||||
if [ -z "${NMTST_SEED_RAND+x}" ]; then
|
||||
NMTST_SEED_RAND="$SRANDOM"
|
||||
if [ -z "$NMTST_SEED_RAND" ]; then
|
||||
@@ -181,6 +186,8 @@ meson setup build \
|
||||
-D ifcfg_rh=false \
|
||||
-D ifupdown=true \
|
||||
\
|
||||
-D nbft=$_WITH_NBFT \
|
||||
\
|
||||
#end
|
||||
|
||||
export NM_TEST_CLIENT_CHECK_L10N=1
|
||||
|
@@ -154,6 +154,7 @@
|
||||
<member><option>net.ifnames</option></member>
|
||||
<member><option>rd.peerdns</option></member>
|
||||
<member><option>rd.iscsi.ibft</option></member>
|
||||
<member><option>rd.nvmf.nonbft</option></member>
|
||||
<member><option>rd.bootif</option></member>
|
||||
<member><option>rd.neednet</option></member>
|
||||
<member><option>rd.ethtool</option></member>
|
||||
|
11
meson.build
11
meson.build
@@ -137,6 +137,9 @@ config_h.set10('HAVE_DECL_REALLOCARRAY', cc.has_function('reallocarray', prefix:
|
||||
config_h.set10('HAVE_DECL_EXPLICIT_BZERO', cc.has_function('explicit_bzero', prefix: '#include <string.h>'))
|
||||
config_h.set10('HAVE_DECL_MEMFD_CREATE', cc.has_function('memfd_create', prefix: '#include <sys/mman.h>'))
|
||||
|
||||
config_h.set10('HAVE_DLVSYM', cc.has_function('dlvsym', prefix: '''#define _GNU_SOURCE
|
||||
#include <dlfcn.h>'''))
|
||||
|
||||
# types
|
||||
config_h.set('SIZEOF_PID_T', cc.sizeof('pid_t', prefix : '#include <sys/types.h>'))
|
||||
config_h.set('SIZEOF_UID_T', cc.sizeof('uid_t', prefix : '#include <sys/types.h>'))
|
||||
@@ -929,6 +932,14 @@ if python.found()
|
||||
config_h.set_quoted('TEST_NM_PYTHON', python_path)
|
||||
endif
|
||||
|
||||
# libnvme (NBFT support)
|
||||
enable_nbft = get_option('nbft')
|
||||
if enable_nbft
|
||||
libnvme_dep = dependency('libnvme', version: '>= 1.5', required: false)
|
||||
assert(libnvme_dep.found(), 'NBFT support was requested, but the libnvme library is not available. Use -Dnbft=false to build without it.')
|
||||
endif
|
||||
config_h.set10('WITH_NBFT', enable_nbft)
|
||||
|
||||
data_conf = configuration_data()
|
||||
data_conf.set('DISTRO_NETWORK_SERVICE', (enable_ifcfg_rh ? 'network.service' : ''))
|
||||
data_conf.set('NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT', config_default_logging_audit)
|
||||
|
@@ -45,6 +45,7 @@ option('nmtui', type: 'boolean', value: true, description: 'Build nmtui')
|
||||
option('nm_cloud_setup', type: 'boolean', value: true, description: 'Build nm-cloud-setup, a tool for automatically configuring networking in cloud')
|
||||
option('bluez5_dun', type: 'boolean', value: false, description: 'enable Bluez5 DUN support')
|
||||
option('ebpf', type: 'combo', choices: ['auto', 'true', 'false'], description: 'Enable eBPF support')
|
||||
option('nbft', type: 'boolean', value: true, description: 'Enable NBFT support in the initrd generator')
|
||||
|
||||
# configuration plugins
|
||||
option('config_plugins_default', type: 'string', value: '', description: 'Default configuration option for main.plugins setting, used as fallback if the configuration option is unset')
|
||||
|
@@ -6,6 +6,7 @@ libnmi_core = static_library(
|
||||
'nmi-cmdline-reader.c',
|
||||
'nmi-dt-reader.c',
|
||||
'nmi-ibft-reader.c',
|
||||
'nmi-nbft-reader.c',
|
||||
),
|
||||
include_directories: [
|
||||
src_inc,
|
||||
|
@@ -41,6 +41,8 @@ nmi_ibft_update_connection_from_nic(NMConnection *connection, GHashTable *nic, G
|
||||
|
||||
NMConnection *nmi_dt_reader_parse(const char *sysfs_dir);
|
||||
|
||||
NMConnection **nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname);
|
||||
|
||||
GHashTable *nmi_cmdline_reader_parse(const char *etc_connections_dir,
|
||||
const char *sysfs_dir,
|
||||
const char *const *argv,
|
||||
|
@@ -1451,8 +1451,10 @@ nmi_cmdline_reader_parse(const char *etc_connections_dir,
|
||||
gs_unref_ptrarray GPtrArray *routes = NULL;
|
||||
gs_unref_ptrarray GPtrArray *znets = NULL;
|
||||
int i;
|
||||
guint64 dhcp_timeout = 90;
|
||||
guint64 dhcp_num_tries = 1;
|
||||
guint64 dhcp_timeout = 90;
|
||||
guint64 dhcp_num_tries = 1;
|
||||
gboolean nvmf_nonbft = FALSE;
|
||||
gboolean have_dracut_nbft = FALSE;
|
||||
|
||||
reader = reader_new();
|
||||
|
||||
@@ -1469,7 +1471,10 @@ nmi_cmdline_reader_parse(const char *etc_connections_dir,
|
||||
/* pass */
|
||||
} else if (nm_streq(tag, "net.ifnames"))
|
||||
net_ifnames = !nm_streq(argument, "0");
|
||||
else if (nm_streq(tag, "rd.peerdns"))
|
||||
else if (nm_streq(tag, "ifname")) {
|
||||
if (NM_STR_HAS_PREFIX(argument, "nbft"))
|
||||
have_dracut_nbft = TRUE;
|
||||
} else if (nm_streq(tag, "rd.peerdns"))
|
||||
reader->ignore_auto_dns = !_nm_utils_ascii_str_to_bool(argument, TRUE);
|
||||
else if (nm_streq(tag, "rd.net.timeout.dhcp")) {
|
||||
if (nm_streq0(argument, "infinity")) {
|
||||
@@ -1561,7 +1566,18 @@ nmi_cmdline_reader_parse(const char *etc_connections_dir,
|
||||
reader_parse_dns_backend(reader, argument);
|
||||
} else if (nm_streq(tag, "rd.net.dns-resolve-mode")) {
|
||||
reader_parse_dns_resolve_mode(reader, argument);
|
||||
} else if (nm_streq(tag, "rd.nvmf.nonbft"))
|
||||
nvmf_nonbft = TRUE;
|
||||
}
|
||||
|
||||
if (!nvmf_nonbft && !have_dracut_nbft) {
|
||||
NMConnection **nbft_connections, **c;
|
||||
|
||||
nbft_connections = nmi_nbft_reader_parse(sysfs_dir, &reader->hostname);
|
||||
for (c = nbft_connections; c && *c; c++) {
|
||||
reader_add_connection(reader, nm_connection_get_id(*c), *c);
|
||||
}
|
||||
g_free(nbft_connections);
|
||||
}
|
||||
|
||||
for (i = 0; i < reader->vlan_parents->len; i++) {
|
||||
|
414
src/nm-initrd-generator/nmi-nbft-reader.c
Normal file
414
src/nm-initrd-generator/nmi-nbft-reader.c
Normal file
@@ -0,0 +1,414 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2024 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "libnm-core-impl/nm-default-libnm-core.h"
|
||||
|
||||
#include "nm-initrd-generator.h"
|
||||
|
||||
#if WITH_NBFT
|
||||
|
||||
#include <libnvme.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "libnm-log-core/nm-logging.h"
|
||||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG(level, domain, ...) \
|
||||
nm_log((level), \
|
||||
(domain), \
|
||||
NULL, \
|
||||
NULL, \
|
||||
"nbft-reader: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) _NM_UTILS_MACRO_REST(__VA_ARGS__))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline gboolean
|
||||
is_valid_addr(int family, const char *addr)
|
||||
{
|
||||
return (addr && strlen(addr) > 0 && !nm_streq(addr, "0.0.0.0") && !nm_streq(addr, "::")
|
||||
&& nm_utils_ipaddr_valid(family, addr));
|
||||
}
|
||||
|
||||
static int (*_nvme_nbft_read)(struct nbft_info **nbft, const char *filename);
|
||||
static void (*_nvme_nbft_free)(struct nbft_info *nbft);
|
||||
|
||||
static void *
|
||||
load_libnvme(void)
|
||||
{
|
||||
void *handle;
|
||||
|
||||
handle = dlopen("libnvme.so.1", RTLD_LAZY);
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
#if HAVE_DLVSYM
|
||||
_nvme_nbft_read = dlvsym(handle, "nvme_nbft_read", "LIBNVME_1_5");
|
||||
_nvme_nbft_free = dlvsym(handle, "nvme_nbft_free", "LIBNVME_1_5");
|
||||
#else
|
||||
/* no dlvsym() in musl */
|
||||
_nvme_nbft_read = dlsym(handle, "nvme_nbft_read");
|
||||
_nvme_nbft_free = dlsym(handle, "nvme_nbft_free");
|
||||
#endif
|
||||
|
||||
if (!_nvme_nbft_read || !_nvme_nbft_free) {
|
||||
dlclose(handle);
|
||||
return NULL;
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
static char *
|
||||
format_conn_name(const char *table_name, struct nbft_info_hfi *hfi, gboolean is_vlan)
|
||||
{
|
||||
if (is_vlan) {
|
||||
nm_assert(hfi->tcp_info.vlan > 0);
|
||||
return g_strdup_printf("%s connection HFI %d VLAN %d",
|
||||
table_name,
|
||||
hfi->index,
|
||||
hfi->tcp_info.vlan);
|
||||
} else
|
||||
return g_strdup_printf("%s connection HFI %d", table_name, hfi->index);
|
||||
}
|
||||
|
||||
static NMConnection *
|
||||
find_conn_for_wired_mac(GPtrArray *a, const char *hwaddr)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < a->len; i++) {
|
||||
NMConnection *con = a->pdata[i];
|
||||
NMSettingWired *s_wired;
|
||||
|
||||
if (!nm_connection_is_type(con, NM_SETTING_WIRED_SETTING_NAME))
|
||||
continue;
|
||||
s_wired = nm_connection_get_setting_wired(con);
|
||||
if (!s_wired)
|
||||
continue;
|
||||
if (nm_streq(hwaddr, nm_setting_wired_get_mac_address(s_wired)))
|
||||
return con;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static NMConnection *
|
||||
create_wired_conn(struct nbft_info_hfi *hfi,
|
||||
const char *conn_name,
|
||||
const char *hwaddr,
|
||||
gboolean is_vlan)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSetting *s_connection;
|
||||
NMSetting *s_wired;
|
||||
|
||||
connection = nm_simple_connection_new();
|
||||
|
||||
s_connection = nm_setting_connection_new();
|
||||
g_object_set(s_connection,
|
||||
NM_SETTING_CONNECTION_TYPE,
|
||||
is_vlan ? NM_SETTING_VLAN_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME,
|
||||
NM_SETTING_CONNECTION_ID,
|
||||
conn_name,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY,
|
||||
NMI_AUTOCONNECT_PRIORITY_FIRMWARE,
|
||||
NULL);
|
||||
nm_connection_add_setting(connection, s_connection);
|
||||
|
||||
/* MAC address */
|
||||
s_wired = nm_setting_wired_new();
|
||||
g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, hwaddr, NULL);
|
||||
nm_connection_add_setting(connection, s_wired);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_hfi(GPtrArray *a, struct nbft_info_hfi *hfi, const char *table_name, char **hostname)
|
||||
{
|
||||
gs_unref_object NMConnection *connection = NULL;
|
||||
NMConnection *parent_connection;
|
||||
NMSetting *s_vlan;
|
||||
gs_free char *hwaddr = NULL;
|
||||
gs_free char *conn_name = NULL;
|
||||
gs_unref_object NMSetting *s_ip4 = NULL;
|
||||
gs_unref_object NMSetting *s_ip6 = NULL;
|
||||
nm_auto_unref_ip_address NMIPAddress *ipaddr = NULL;
|
||||
guint prefix;
|
||||
gs_free_error GError *error = NULL;
|
||||
int family = AF_UNSPEC;
|
||||
NMIPAddr addr_bin;
|
||||
|
||||
/* Pre-checks */
|
||||
if (!nm_inet_parse_bin_full(family, FALSE, hfi->tcp_info.ipaddr, &family, &addr_bin)) {
|
||||
_LOGW(LOGD_CORE, "NBFT: Malformed IP address: '%s'", hfi->tcp_info.ipaddr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* MAC address */
|
||||
hwaddr = g_strdup_printf("%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
hfi->tcp_info.mac_addr[0],
|
||||
hfi->tcp_info.mac_addr[1],
|
||||
hfi->tcp_info.mac_addr[2],
|
||||
hfi->tcp_info.mac_addr[3],
|
||||
hfi->tcp_info.mac_addr[4],
|
||||
hfi->tcp_info.mac_addr[5]);
|
||||
|
||||
/* First check if we need VLANs */
|
||||
if (hfi->tcp_info.vlan > 0) {
|
||||
parent_connection = find_conn_for_wired_mac(a, hwaddr);
|
||||
if (!parent_connection) {
|
||||
/* Create new parent wired connection */
|
||||
conn_name = format_conn_name(table_name, hfi, FALSE);
|
||||
parent_connection = create_wired_conn(hfi, conn_name, hwaddr, FALSE);
|
||||
|
||||
s_ip4 = nm_setting_ip4_config_new();
|
||||
s_ip6 = nm_setting_ip6_config_new();
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
|
||||
NULL);
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
|
||||
NULL);
|
||||
nm_connection_add_setting(parent_connection, g_steal_pointer(&s_ip4));
|
||||
nm_connection_add_setting(parent_connection, g_steal_pointer(&s_ip6));
|
||||
|
||||
if (!nm_connection_normalize(parent_connection, NULL, NULL, &error)) {
|
||||
_LOGW(LOGD_CORE, "Generated an invalid connection: %s", error->message);
|
||||
g_object_unref(parent_connection);
|
||||
return;
|
||||
}
|
||||
g_ptr_array_add(a, parent_connection);
|
||||
}
|
||||
|
||||
conn_name = format_conn_name(table_name, hfi, TRUE);
|
||||
connection = create_wired_conn(hfi, conn_name, hwaddr, TRUE);
|
||||
|
||||
s_vlan = nm_setting_vlan_new();
|
||||
g_object_set(s_vlan, NM_SETTING_VLAN_ID, hfi->tcp_info.vlan, NULL);
|
||||
nm_connection_add_setting(connection, s_vlan);
|
||||
} else {
|
||||
/* No VLANS */
|
||||
conn_name = format_conn_name(table_name, hfi, FALSE);
|
||||
connection = create_wired_conn(hfi, conn_name, hwaddr, FALSE);
|
||||
}
|
||||
|
||||
/* IP addresses */
|
||||
s_ip4 = nm_setting_ip4_config_new();
|
||||
s_ip6 = nm_setting_ip6_config_new();
|
||||
|
||||
switch (family) {
|
||||
/* IPv4 */
|
||||
case AF_INET:
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
|
||||
NULL);
|
||||
if (is_valid_addr(AF_INET, hfi->tcp_info.dhcp_server_ipaddr)) {
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
||||
NULL);
|
||||
if (hfi->tcp_info.host_name && strlen(hfi->tcp_info.host_name) > 0) {
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_DHCP_HOSTNAME,
|
||||
hfi->tcp_info.host_name,
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||
NULL);
|
||||
ipaddr = nm_ip_address_new_binary(AF_INET,
|
||||
&addr_bin,
|
||||
hfi->tcp_info.subnet_mask_prefix,
|
||||
&error);
|
||||
if (!ipaddr) {
|
||||
_LOGW(LOGD_CORE,
|
||||
"Cannot parse IP %s/%u: %s",
|
||||
hfi->tcp_info.ipaddr,
|
||||
hfi->tcp_info.subnet_mask_prefix,
|
||||
error->message);
|
||||
return;
|
||||
}
|
||||
nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(s_ip4), ipaddr);
|
||||
if (is_valid_addr(AF_INET, hfi->tcp_info.gateway_ipaddr)) {
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
hfi->tcp_info.gateway_ipaddr,
|
||||
NULL);
|
||||
}
|
||||
if (is_valid_addr(AF_INET, hfi->tcp_info.primary_dns_ipaddr)) {
|
||||
nm_setting_ip_config_add_dns(NM_SETTING_IP_CONFIG(s_ip4),
|
||||
hfi->tcp_info.primary_dns_ipaddr);
|
||||
}
|
||||
if (is_valid_addr(AF_INET, hfi->tcp_info.secondary_dns_ipaddr)) {
|
||||
nm_setting_ip_config_add_dns(NM_SETTING_IP_CONFIG(s_ip4),
|
||||
hfi->tcp_info.secondary_dns_ipaddr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* IPv6 */
|
||||
case AF_INET6:
|
||||
g_object_set(s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
|
||||
NULL);
|
||||
if (is_valid_addr(AF_INET6, hfi->tcp_info.dhcp_server_ipaddr)) {
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
||||
NULL);
|
||||
if (hfi->tcp_info.host_name && strlen(hfi->tcp_info.host_name) > 0) {
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_DHCP_HOSTNAME,
|
||||
hfi->tcp_info.host_name,
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
|
||||
NULL);
|
||||
prefix = hfi->tcp_info.subnet_mask_prefix;
|
||||
if (prefix == 0) {
|
||||
/* Buggy firmware implementations may report prefix=0 for v6 addresses,
|
||||
* let's fall back to /64.
|
||||
*/
|
||||
_LOGW(LOGD_CORE,
|
||||
"NBFT: Invalid IPv6 prefix %d, using /64 as a fallback.",
|
||||
hfi->tcp_info.subnet_mask_prefix);
|
||||
prefix = 64;
|
||||
}
|
||||
ipaddr = nm_ip_address_new_binary(AF_INET6, &addr_bin, prefix, &error);
|
||||
if (!ipaddr) {
|
||||
_LOGW(LOGD_CORE,
|
||||
"Cannot parse IP %s/%u: %s",
|
||||
hfi->tcp_info.ipaddr,
|
||||
prefix,
|
||||
error->message);
|
||||
return;
|
||||
}
|
||||
nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(s_ip6), ipaddr);
|
||||
if (is_valid_addr(AF_INET6, hfi->tcp_info.gateway_ipaddr)) {
|
||||
g_object_set(s_ip6,
|
||||
NM_SETTING_IP_CONFIG_GATEWAY,
|
||||
hfi->tcp_info.gateway_ipaddr,
|
||||
NULL);
|
||||
}
|
||||
if (is_valid_addr(AF_INET6, hfi->tcp_info.primary_dns_ipaddr)) {
|
||||
nm_setting_ip_config_add_dns(NM_SETTING_IP_CONFIG(s_ip6),
|
||||
hfi->tcp_info.primary_dns_ipaddr);
|
||||
}
|
||||
if (is_valid_addr(AF_INET6, hfi->tcp_info.secondary_dns_ipaddr)) {
|
||||
nm_setting_ip_config_add_dns(NM_SETTING_IP_CONFIG(s_ip6),
|
||||
hfi->tcp_info.secondary_dns_ipaddr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warn_if_reached();
|
||||
}
|
||||
|
||||
nm_connection_add_setting(connection, g_steal_pointer(&s_ip4));
|
||||
nm_connection_add_setting(connection, g_steal_pointer(&s_ip6));
|
||||
|
||||
/* Hostname */
|
||||
if (hfi->tcp_info.host_name && strlen(hfi->tcp_info.host_name) > 0) {
|
||||
g_free(*hostname);
|
||||
*hostname = g_strdup(hfi->tcp_info.host_name);
|
||||
}
|
||||
|
||||
/* TODO: translate the following HFI struct members?
|
||||
* hfi->tcp_info.pci_sbdf
|
||||
* hfi->tcp_info.ip_origin
|
||||
* hfi->tcp_info.dhcp_server_ipaddr
|
||||
* hfi->tcp_info.this_hfi_is_default_route
|
||||
* hfi->tcp_info.dhcp_override
|
||||
*/
|
||||
|
||||
if (!nm_connection_normalize(connection, NULL, NULL, &error)) {
|
||||
_LOGW(LOGD_CORE, "Generated an invalid connection: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
g_ptr_array_add(a, g_steal_pointer(&connection));
|
||||
}
|
||||
|
||||
NMConnection **
|
||||
nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
|
||||
{
|
||||
nm_auto_unref_ptrarray GPtrArray *a = NULL;
|
||||
gs_free char *path = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
GDir *dir;
|
||||
void *libnvme_handle = NULL;
|
||||
const char *entry_name;
|
||||
|
||||
g_return_val_if_fail(sysfs_dir != NULL, NULL);
|
||||
path = g_build_filename(sysfs_dir, "firmware", "acpi", "tables", NULL);
|
||||
|
||||
dir = g_dir_open(path, 0, NULL);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
|
||||
a = g_ptr_array_new();
|
||||
|
||||
while ((entry_name = g_dir_read_name(dir))) {
|
||||
gs_free char *entry_path = NULL;
|
||||
struct nbft_info *nbft;
|
||||
struct nbft_info_hfi **hfi;
|
||||
int ret;
|
||||
|
||||
if (!g_str_has_prefix(entry_name, "NBFT"))
|
||||
continue;
|
||||
|
||||
/* attempt to load libnvme only on the first table match, saving some I/O */
|
||||
if (!libnvme_handle && !(libnvme_handle = load_libnvme())) {
|
||||
g_dir_close(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry_path = g_build_filename(path, entry_name, NULL);
|
||||
ret = _nvme_nbft_read(&nbft, entry_path);
|
||||
if (ret) {
|
||||
_LOGW(LOGD_CORE, "Error parsing NBFT table %s: %m", entry_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (hfi = nbft->hfi_list; hfi && *hfi; hfi++) {
|
||||
if (!nm_streq((*hfi)->transport, "tcp")) {
|
||||
_LOGW(LOGD_CORE,
|
||||
"NBFT table %s, HFI descriptor %d: unsupported transport type '%s'",
|
||||
entry_path,
|
||||
(*hfi)->index,
|
||||
(*hfi)->transport);
|
||||
continue;
|
||||
}
|
||||
parse_hfi(a, *hfi, entry_name, hostname);
|
||||
}
|
||||
|
||||
_nvme_nbft_free(nbft);
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
dlclose(libnvme_handle);
|
||||
g_ptr_array_add(a, NULL); /* trailing NULL-delimiter */
|
||||
return (NMConnection **) g_ptr_array_free(g_steal_pointer(&a), FALSE);
|
||||
}
|
||||
|
||||
#else /* WITH_NBFT */
|
||||
|
||||
NMConnection **
|
||||
nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
@@ -224,6 +224,7 @@ RUN dnf install -y \\
|
||||
libasan \\
|
||||
libcurl-devel \\
|
||||
libndp-devel \\
|
||||
libnvme-devel \\
|
||||
libpsl-devel \\
|
||||
libselinux-devel \\
|
||||
libtool \\
|
||||
|
Reference in New Issue
Block a user