initrd: VLAN support for the NBFT parser

Creates additional connections for VLANs, which are in fact
separate HFI records in the NBFT table. Uses MAC address for
linking parent interface as the interface naming is defined
by an external service.

Signed-off-by: Tomas Bzatek <tbzatek@redhat.com>
This commit is contained in:
Tomas Bzatek
2024-12-10 19:22:14 +01:00
committed by Beniamino Galvani
parent 8b7c6f8b90
commit d38cbfb3d1

View File

@@ -61,45 +61,57 @@ load_libnvme(void)
return handle; return handle;
} }
static NMConnection * static char *
parse_hfi(struct nbft_info_hfi *hfi, int iface_idx, char **hostname) format_conn_name(const char *table_name, struct nbft_info_hfi *hfi, gboolean is_vlan)
{ {
gs_unref_object NMConnection *connection; if (is_vlan) {
NMSetting *s_connection; nm_assert(hfi->tcp_info.vlan > 0);
NMSetting *s_wired; return g_strdup_printf("%s connection HFI %d VLAN %d",
gs_free char *hwaddr = NULL; table_name,
gs_free char *ifname = NULL; hfi->index,
gs_unref_object NMSetting *s_ip4 = NULL; hfi->tcp_info.vlan);
gs_unref_object NMSetting *s_ip6 = NULL; } else
nm_auto_unref_ip_address NMIPAddress *ipaddr = NULL; return g_strdup_printf("%s connection HFI %d", table_name, hfi->index);
gs_free_error GError *error = NULL; }
int family = AF_UNSPEC;
NMIPAddr addr_bin;
/* Pre-checks */ static NMConnection *
if (!nm_inet_parse_bin_full(family, FALSE, hfi->tcp_info.ipaddr, &family, &addr_bin)) { find_conn_for_wired_mac(GPtrArray *a, const char *hwaddr)
_LOGW(LOGD_CORE, "NBFT: Malformed IP address: '%s'", hfi->tcp_info.ipaddr); {
return NULL; 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;
}
ifname = g_strdup_printf("NBFT connection %d", iface_idx); static NMConnection *
hwaddr = g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", create_wired_conn(struct nbft_info_hfi *hfi,
hfi->tcp_info.mac_addr[0], const char *conn_name,
hfi->tcp_info.mac_addr[1], const char *hwaddr,
hfi->tcp_info.mac_addr[2], gboolean is_vlan)
hfi->tcp_info.mac_addr[3], {
hfi->tcp_info.mac_addr[4], NMConnection *connection;
hfi->tcp_info.mac_addr[5]); NMSetting *s_connection;
NMSetting *s_wired;
/* Create new connection */
connection = nm_simple_connection_new(); connection = nm_simple_connection_new();
s_connection = nm_setting_connection_new(); s_connection = nm_setting_connection_new();
g_object_set(s_connection, g_object_set(s_connection,
NM_SETTING_CONNECTION_TYPE, NM_SETTING_CONNECTION_TYPE,
NM_SETTING_WIRED_SETTING_NAME, is_vlan ? NM_SETTING_VLAN_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_CONNECTION_ID, NM_SETTING_CONNECTION_ID,
ifname, conn_name,
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY,
NMI_AUTOCONNECT_PRIORITY_FIRMWARE, NMI_AUTOCONNECT_PRIORITY_FIRMWARE,
NULL); NULL);
@@ -110,7 +122,80 @@ parse_hfi(struct nbft_info_hfi *hfi, int iface_idx, char **hostname)
g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, hwaddr, NULL); g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, hwaddr, NULL);
nm_connection_add_setting(connection, s_wired); nm_connection_add_setting(connection, s_wired);
/* TODO: hfi->tcp_info.vlan */ 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 */ /* IP addresses */
s_ip4 = nm_setting_ip4_config_new(); s_ip4 = nm_setting_ip4_config_new();
@@ -149,7 +234,7 @@ parse_hfi(struct nbft_info_hfi *hfi, int iface_idx, char **hostname)
hfi->tcp_info.ipaddr, hfi->tcp_info.ipaddr,
hfi->tcp_info.subnet_mask_prefix, hfi->tcp_info.subnet_mask_prefix,
error->message); error->message);
return NULL; return;
} }
nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(s_ip4), ipaddr); nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(s_ip4), ipaddr);
if (is_valid_addr(AF_INET, hfi->tcp_info.gateway_ipaddr)) { if (is_valid_addr(AF_INET, hfi->tcp_info.gateway_ipaddr)) {
@@ -204,7 +289,7 @@ parse_hfi(struct nbft_info_hfi *hfi, int iface_idx, char **hostname)
hfi->tcp_info.ipaddr, hfi->tcp_info.ipaddr,
prefix, prefix,
error->message); error->message);
return NULL; return;
} }
nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(s_ip6), ipaddr); nm_setting_ip_config_add_address(NM_SETTING_IP_CONFIG(s_ip6), ipaddr);
if (is_valid_addr(AF_INET6, hfi->tcp_info.gateway_ipaddr)) { if (is_valid_addr(AF_INET6, hfi->tcp_info.gateway_ipaddr)) {
@@ -246,9 +331,10 @@ parse_hfi(struct nbft_info_hfi *hfi, int iface_idx, char **hostname)
if (!nm_connection_normalize(connection, NULL, NULL, &error)) { if (!nm_connection_normalize(connection, NULL, NULL, &error)) {
_LOGW(LOGD_CORE, "Generated an invalid connection: %s", error->message); _LOGW(LOGD_CORE, "Generated an invalid connection: %s", error->message);
return NULL; return;
} }
return g_steal_pointer(&connection);
g_ptr_array_add(a, g_steal_pointer(&connection));
} }
NMConnection ** NMConnection **
@@ -260,7 +346,6 @@ nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
GDir *dir; GDir *dir;
void *libnvme_handle = NULL; void *libnvme_handle = NULL;
const char *entry_name; const char *entry_name;
int idx = 1;
g_return_val_if_fail(sysfs_dir != NULL, NULL); g_return_val_if_fail(sysfs_dir != NULL, NULL);
path = g_build_filename(sysfs_dir, "firmware", "acpi", "tables", NULL); path = g_build_filename(sysfs_dir, "firmware", "acpi", "tables", NULL);
@@ -293,9 +378,7 @@ nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
continue; continue;
} }
for (hfi = nbft->hfi_list; hfi && *hfi; hfi++, idx++) { for (hfi = nbft->hfi_list; hfi && *hfi; hfi++) {
NMConnection *connection;
if (!nm_streq((*hfi)->transport, "tcp")) { if (!nm_streq((*hfi)->transport, "tcp")) {
_LOGW(LOGD_CORE, _LOGW(LOGD_CORE,
"NBFT table %s, HFI descriptor %d: unsupported transport type '%s'", "NBFT table %s, HFI descriptor %d: unsupported transport type '%s'",
@@ -304,10 +387,7 @@ nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
(*hfi)->transport); (*hfi)->transport);
continue; continue;
} }
parse_hfi(a, *hfi, entry_name, hostname);
connection = parse_hfi(*hfi, idx, hostname);
if (connection)
g_ptr_array_add(a, connection);
} }
_nvme_nbft_free(nbft); _nvme_nbft_free(nbft);
@@ -316,7 +396,7 @@ nmi_nbft_reader_parse(const char *sysfs_dir, char **hostname)
g_dir_close(dir); g_dir_close(dir);
dlclose(libnvme_handle); dlclose(libnvme_handle);
g_ptr_array_add(a, NULL); /* trailing NULL-delimiter */ g_ptr_array_add(a, NULL); /* trailing NULL-delimiter */
return (NMConnection **) g_ptr_array_free(a, FALSE); return (NMConnection **) g_ptr_array_free(g_steal_pointer(&a), FALSE);
} }
#else /* WITH_NBFT */ #else /* WITH_NBFT */