diff --git a/doc/netplan-yaml.md b/doc/netplan-yaml.md index 9963f6d1a..3071cdefc 100644 --- a/doc/netplan-yaml.md +++ b/doc/netplan-yaml.md @@ -374,11 +374,19 @@ Match devices by MAC when setting options like: `wakeonlan` or `*-offload`. > (networkd backend only) Allow the specified interface to be configured even > if it has no carrier. -- **critical** (bool) +- **critical** (scalar) - > Designate the connection as "critical to the system", meaning that special - > care will be taken by to not release the assigned IP when the daemon is - > restarted. (not recognized by NetworkManager) + > This option sets the systemd KeepConfiguration option. + > (not recognized by NetworkManager) + > + > When set to "static", static addresses and routes won't be dropped on + > starting up process. + > When set to "dhcp-on-stop", addresses and routes won't be dropped when + > stopping the daemon. + > When set to "dhcp", addresses and routes provided by a DHCP server will + > never be dropped even if the DHCP lease expires, implies "dhcp-on-stop". + > When set to "yes", "dhcp" and "static" is implied. + > Defaults to "no". - **dhcp-identifier** (scalar) diff --git a/python-cffi/netplan/_build_cffi.py b/python-cffi/netplan/_build_cffi.py index ba0af4ec8..4a136c6f6 100644 --- a/python-cffi/netplan/_build_cffi.py +++ b/python-cffi/netplan/_build_cffi.py @@ -34,6 +34,7 @@ typedef struct netplan_net_definition NetplanNetDefinition; typedef enum { ... } NetplanBackend; typedef enum { ... } NetplanDefType; + typedef enum { ... } NetplanCriticalOption; // TODO: Introduce getters for .address/.lifetime/.label to avoid exposing the raw struct typedef struct { @@ -112,7 +113,7 @@ ssize_t _netplan_netdef_get_embedded_switch_mode(const NetplanNetDefinition* netdef, char* out_buffer, size_t out_buf_size); gboolean _netplan_netdef_get_sriov_vlan_filter(const NetplanNetDefinition* netdef); guint _netplan_netdef_get_vlan_id(const NetplanNetDefinition* netdef); - gboolean _netplan_netdef_get_critical(const NetplanNetDefinition* netdef); + NetplanCriticalOption _netplan_netdef_get_critical(const NetplanNetDefinition* netdef); gboolean _netplan_netdef_is_trivial_compound_itf(const NetplanNetDefinition* netdef); int _netplan_state_get_vf_count_for_def( const NetplanState* np_state, const NetplanNetDefinition* netdef, NetplanError** error); diff --git a/src/abi.h b/src/abi.h index 11f62ab07..45917d750 100644 --- a/src/abi.h +++ b/src/abi.h @@ -32,6 +32,14 @@ typedef enum { NETPLAN_OPTIONAL_STATIC = 1<<4, } NetplanOptionalAddressFlag; +typedef enum { + NETPLAN_CRITICAL_FALSE, + NETPLAN_CRITICAL_TRUE, + NETPLAN_CRITICAL_STATIC, + NETPLAN_CRITICAL_DHCP, + NETPLAN_CRITICAL_DHCP_ON_STOP, +} NetplanCriticalOption; + /* Fields below are valid for dhcp4 and dhcp6 unless otherwise noted. */ typedef struct dhcp_overrides { gboolean use_dns; @@ -211,7 +219,7 @@ struct netplan_net_definition { /* status options */ gboolean optional; NetplanOptionalAddressFlag optional_addresses; - gboolean critical; + NetplanCriticalOption critical; /* addresses */ gboolean dhcp4; diff --git a/src/netplan.c b/src/netplan.c index 81bddb534..5fd29dc46 100644 --- a/src/netplan.c +++ b/src/netplan.c @@ -742,8 +742,18 @@ _serialize_yaml( if (def->optional) YAML_NONNULL_STRING_PLAIN(event, emitter, "optional", "true"); - if (def->critical) + + if (def->critical == NETPLAN_CRITICAL_TRUE) { YAML_NONNULL_STRING_PLAIN(event, emitter, "critical", "true"); + } else if (def->critical == NETPLAN_CRITICAL_FALSE) { + YAML_NONNULL_STRING_PLAIN(event, emitter, "critical", "false"); + } else if (def->critical == NETPLAN_CRITICAL_STATIC) { + YAML_NONNULL_STRING_PLAIN(event, emitter, "critical", "static"); + } else if (def->critical == NETPLAN_CRITICAL_DHCP) { + YAML_NONNULL_STRING_PLAIN(event, emitter, "critical", "dhcp"); + } else if (def->critical == NETPLAN_CRITICAL_DHCP_ON_STOP) { + YAML_NONNULL_STRING_PLAIN(event, emitter, "critical", "dhcp-on-stop"); + } if (def->ignore_carrier) YAML_NONNULL_STRING_PLAIN(event, emitter, "ignore-carrier", "true"); diff --git a/src/networkd.c b/src/networkd.c index 580304c37..608d36e6c 100644 --- a/src/networkd.c +++ b/src/networkd.c @@ -353,7 +353,7 @@ write_bond_parameters(const NetplanNetDefinition* def, GString* s) if (def->bond_params.selection_logic) g_string_append_printf(params, "\nAdSelect=%s", def->bond_params.selection_logic); if (def->bond_params.all_members_active) - g_string_append_printf(params, "\nAllSlavesActive=%d", def->bond_params.all_members_active); /* wokeignore:rule=slave */ + g_string_append_printf(params, "\nAllSlavesActive=%d", def->bond_params.all_members_active); /* wokeignore:rule=slave */ if (def->bond_params.arp_interval) { g_string_append(params, "\nARPIntervalSec="); if (interval_has_suffix(def->bond_params.arp_interval)) @@ -393,7 +393,7 @@ write_bond_parameters(const NetplanNetDefinition* def, GString* s) g_string_append_printf(params, "\nGratuitousARP=%d", def->bond_params.gratuitous_arp); /* TODO: add unsolicited_na, not documented as supported by NM. */ if (def->bond_params.packets_per_member) - g_string_append_printf(params, "\nPacketsPerSlave=%d", def->bond_params.packets_per_member); /* wokeignore:rule=slave */ + g_string_append_printf(params, "\nPacketsPerSlave=%d", def->bond_params.packets_per_member); /* wokeignore:rule=slave */ if (def->bond_params.primary_reselect_policy) g_string_append_printf(params, "\nPrimaryReselectPolicy=%s", def->bond_params.primary_reselect_policy); if (def->bond_params.resend_igmp) @@ -921,8 +921,21 @@ netplan_netdef_write_network_file( g_string_append(network, "\n[DHCP]\n"); } - if (def->critical) - g_string_append_printf(network, "CriticalConnection=true\n"); + switch (def->critical) { + case NETPLAN_CRITICAL_TRUE: + g_string_append(s, "KeepConnection=true\n"); + break; + case NETPLAN_CRITICAL_STATIC: + g_string_append(s, "KeepConnection=static\n"); + break; + case NETPLAN_CRITICAL_DHCP: + g_string_append(s, "KeepConnection=dhcp\n"); + break; + case NETPLAN_CRITICAL_DHCP_ON_STOP: + g_string_append(s, "KeepConnection=dhcp-on-stop\n"); + break; + default: g_assert_not_reached(); // LCOV_EXCL_LINE + } if (def->dhcp4 || def->dhcp6) { if (def->dhcp_identifier) diff --git a/src/types.c b/src/types.c index 462389087..3c8b73b75 100644 --- a/src/types.c +++ b/src/types.c @@ -225,7 +225,7 @@ reset_netdef(NetplanNetDefinition* netdef, NetplanDefType new_type, NetplanBacke netdef->optional = FALSE; netdef->optional_addresses = 0; - netdef->critical = FALSE; + netdef->critical = NETPLAN_CRITICAL_FALSE; netdef->dhcp4 = FALSE; netdef->dhcp6 = FALSE; @@ -594,7 +594,7 @@ _netplan_netdef_get_vlan_id(const NetplanNetDefinition* netdef) return netdef->vlan_id; } -gboolean +NetplanCriticalOption _netplan_netdef_get_critical(const NetplanNetDefinition* netdef) { g_assert(netdef); diff --git a/src/util-internal.h b/src/util-internal.h index a27e771dd..2db88b75c 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -102,7 +102,7 @@ _netplan_state_get_vf_count_for_def(const NetplanState* np_state, const NetplanN NETPLAN_INTERNAL gboolean _netplan_netdef_get_sriov_vlan_filter(const NetplanNetDefinition* netdef); -NETPLAN_INTERNAL gboolean +NETPLAN_INTERNAL NetplanCriticalOption _netplan_netdef_get_critical(const NetplanNetDefinition* netdef); NETPLAN_INTERNAL gboolean diff --git a/tests/generator/test_common.py b/tests/generator/test_common.py index ad96b787b..237142aaa 100644 --- a/tests/generator/test_common.py +++ b/tests/generator/test_common.py @@ -482,7 +482,7 @@ def test_dhcp_critical_true(self): LinkLocalAddressing=ipv6 [DHCP] -CriticalConnection=true +KeepConfiguration=true '''}) def test_dhcp_identifier_mac(self):