nm-initrd-generator: rework NBFT HFI DHCP detection

There are several flags specified in the NVMe Boot Specification
that may indicate DHCP was used to acquire information during the
pre-OS phase. This commit considers these additional sources,
based on actual NBFT table contents from different systems.

Although we've seen slight variations in firmware implementations
regarding the HFI IP Origin values when DHCP was configured, the
new set of rules still align with expectations.

(cherry picked from commit 6304d51440)
This commit is contained in:
Tomas Bzatek 2025-08-15 16:40:01 +02:00 committed by Beniamino Galvani
parent 862277bda9
commit 2df9da3d2b

View file

@ -94,6 +94,33 @@ find_conn_for_wired_mac(GPtrArray *a, const char *hwaddr)
return NULL;
}
static gboolean
hfi_is_dhcp(struct nbft_info_hfi *hfi, int family)
{
/* There are several flags that may indicate the HFI is set for DHCP
* per NVM Express® Boot Specification, Revision 1.3. As the HFI
* Transport Flags (HFITFLAGS) are not publicly exposed by the libnvme
* API, only the DHCP Override (DHCPO) flag and the IP Origin (IPORIG)
* value is available.
*
* The bit 03 of the HFI Transport Flags (HFITFLAGS) is about an advanced
* stateless mechanism - IPv6-SLAAC and IPv6-ND, stating that "the DHCP
* Override bit shall be cleared to 0, and the IP Origin field shall
* be cleared to 0". This nm-initrd-generator will ignore this flag,
* expecting an IP address to be provided by the usual HFI fields
* just like in a static adressing case.
*
* DHCP Override (DHCPO): "The HFI information was populated by
* consuming the DHCP on this interface."
*
* IP Origin (IPORIG): "If set to 3h (IpPrefixOriginDhcp), then the
* IP Address was acquired through DHCP, and the IP Address specified
* in this HFI should not be reused by the OS."
*/
return hfi->tcp_info.dhcp_override || hfi->tcp_info.ip_origin == 3 /* IpPrefixOriginDhcp */
|| is_valid_addr(family, hfi->tcp_info.dhcp_server_ipaddr);
}
static NMConnection *
create_wired_conn(struct nbft_info_hfi *hfi,
const char *conn_name,
@ -208,7 +235,7 @@ parse_hfi(GPtrArray *a, struct nbft_info_hfi *hfi, const char *table_name, char
NM_SETTING_IP_CONFIG_METHOD,
NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
NULL);
if (is_valid_addr(AF_INET, hfi->tcp_info.dhcp_server_ipaddr)) {
if (hfi_is_dhcp(hfi, family)) {
g_object_set(s_ip4,
NM_SETTING_IP_CONFIG_METHOD,
NM_SETTING_IP4_CONFIG_METHOD_AUTO,
@ -260,7 +287,7 @@ parse_hfi(GPtrArray *a, struct nbft_info_hfi *hfi, const char *table_name, char
NM_SETTING_IP_CONFIG_METHOD,
NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
NULL);
if (is_valid_addr(AF_INET6, hfi->tcp_info.dhcp_server_ipaddr)) {
if (hfi_is_dhcp(hfi, family)) {
g_object_set(s_ip6,
NM_SETTING_IP_CONFIG_METHOD,
NM_SETTING_IP6_CONFIG_METHOD_AUTO,