mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-06 12:58:22 +03:00
network: add ActivationPolicy= configuration parameter
This parameter allows configuring the activation policy for an interface, meaning how it manages the interface's administrative state (IFF_UP flag). The policy can be configured to bring the interface either up or down when the interface is (re)configured, to always force the interface either up or down, or to never change the interface administrative state. If the interface is bound with BindCarrier=, its administrative state is controlled by the interface(s) it's bound to, and this parameter is forced to 'bound'. This changes the default behavior of how systemd-networkd sets the IFF_UP flag; previously, it was set up (if not already up) every time the link_joined() function was called. Now, with the default ActivationPolicy= setting of 'up', it will only set the IFF_UP flag once, the first time link_joined() is called, during an interface's configuration; and on the first link_joined() call each time the interface is reconfigured. Fixes: #3031 Fixes: #17437
This commit is contained in:
parent
fee6441601
commit
61135582e0
@ -249,6 +249,36 @@
|
|||||||
if <literal>RequiredForOnline=no</literal>.</para>
|
if <literal>RequiredForOnline=no</literal>.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>ActivationPolicy=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Specifies the policy for <command>systemd-networkd</command> managing the link
|
||||||
|
administrative state. Specifically, this controls how <command>systemd-networkd</command>
|
||||||
|
changes the network device's <literal>IFF_UP</literal> flag, which is sometimes
|
||||||
|
controlled by system administrators by running e.g., <command>ip set dev eth0 up</command>
|
||||||
|
or <command>ip set dev eth0 down</command>, and can also be changed with
|
||||||
|
<command>networkctl up eth0</command> or <command>networkctl down eth0</command>.</para>
|
||||||
|
|
||||||
|
<para>Takes one of <literal>up</literal>, <literal>always-up</literal>,
|
||||||
|
<literal>manual</literal>, <literal>always-down</literal>, <literal>down</literal>,
|
||||||
|
or <literal>bound</literal>. When <literal>manual</literal>, <command>systemd-networkd</command>
|
||||||
|
will not change the link's admin state automatically; the system administrator must bring the
|
||||||
|
interface up or down manually, as desired. When <literal>up</literal> (the default) or
|
||||||
|
<literal>always-up</literal>, or <literal>down</literal> or <literal>always-down</literal>,
|
||||||
|
<command>systemd-networkd</command> will set the link up or down, respectively,
|
||||||
|
when the interface is (re)configured. When <literal>always-up</literal> or
|
||||||
|
<literal>always-down</literal>, <command>systemd-networkd</command> will set the link up
|
||||||
|
or down, respectively, any time <command>systemd-networkd</command> detects a change in
|
||||||
|
the administrative state. When <varname>BindCarrier=</varname> is also set, this is
|
||||||
|
automatically set to <literal>bound</literal> and any other value is ignored.</para>
|
||||||
|
|
||||||
|
<para>The administrative state is not the same as the carrier state, so using
|
||||||
|
<literal>always-up</literal> does not mean the link will never lose carrier. The link
|
||||||
|
carrier depends on both the administrative state as well as the network device's physical
|
||||||
|
connection. However, to avoid reconfiguration failures, when using <literal>always-up</literal>,
|
||||||
|
<varname>IgnoreCarrierLoss=</varname> is forced to true.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@ -592,8 +622,9 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>A link name or a list of link names. When set, controls the behavior of the current
|
<para>A link name or a list of link names. When set, controls the behavior of the current
|
||||||
link. When all links in the list are in an operational down state, the current link is brought
|
link. When all links in the list are in an operational down state, the current link is brought
|
||||||
down. When at least one link has carrier, the current interface is brought up.
|
down. When at least one link has carrier, the current interface is brought up.</para>
|
||||||
</para>
|
|
||||||
|
<para>This forces <varname>ActivationPolicy=</varname> to be set to <literal>bound</literal>.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@ -966,6 +997,10 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
|||||||
of the interface even if its carrier is lost. When unset, the value specified with
|
of the interface even if its carrier is lost. When unset, the value specified with
|
||||||
<option>ConfigureWithoutCarrier=</option> is used.
|
<option>ConfigureWithoutCarrier=</option> is used.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>When <varname>ActivationPolicy=</varname> is set to <literal>always-up</literal>, this
|
||||||
|
is forced to <literal>true</literal>.
|
||||||
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -1831,17 +1831,38 @@ static int link_joined(Link *link) {
|
|||||||
assert(link);
|
assert(link);
|
||||||
assert(link->network);
|
assert(link->network);
|
||||||
|
|
||||||
if (!hashmap_isempty(link->bound_to_links)) {
|
switch (link->network->activation_policy) {
|
||||||
|
case ACTIVATION_POLICY_BOUND:
|
||||||
r = link_handle_bound_to_list(link);
|
r = link_handle_bound_to_list(link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else if (!(link->flags & IFF_UP)) {
|
break;
|
||||||
|
case ACTIVATION_POLICY_UP:
|
||||||
|
if (link->activated)
|
||||||
|
break;
|
||||||
|
_fallthrough_;
|
||||||
|
case ACTIVATION_POLICY_ALWAYS_UP:
|
||||||
r = link_up(link);
|
r = link_up(link);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
link_enter_failed(link);
|
link_enter_failed(link);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case ACTIVATION_POLICY_DOWN:
|
||||||
|
if (link->activated)
|
||||||
|
break;
|
||||||
|
_fallthrough_;
|
||||||
|
case ACTIVATION_POLICY_ALWAYS_DOWN:
|
||||||
|
r = link_down(link, NULL);
|
||||||
|
if (r < 0) {
|
||||||
|
link_enter_failed(link);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
link->activated = true;
|
||||||
|
|
||||||
if (link->network->bridge) {
|
if (link->network->bridge) {
|
||||||
r = link_set_bridge(link);
|
r = link_set_bridge(link);
|
||||||
@ -2254,6 +2275,7 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
link_set_state(link, LINK_STATE_INITIALIZED);
|
link_set_state(link, LINK_STATE_INITIALIZED);
|
||||||
|
link->activated = false;
|
||||||
link_dirty(link);
|
link_dirty(link);
|
||||||
|
|
||||||
/* link_configure_duid() returns 0 if it requests product UUID. In that case,
|
/* link_configure_duid() returns 0 if it requests product UUID. In that case,
|
||||||
@ -2658,6 +2680,16 @@ int link_carrier_reset(Link *link) {
|
|||||||
static int link_admin_state_up(Link *link) {
|
static int link_admin_state_up(Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
|
||||||
|
if (!link->network)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_DOWN) {
|
||||||
|
log_link_info(link, "ActivationPolicy is \"always-off\", forcing link down");
|
||||||
|
return link_down(link, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* We set the ipv6 mtu after the device mtu, but the kernel resets
|
/* We set the ipv6 mtu after the device mtu, but the kernel resets
|
||||||
* ipv6 mtu on NETDEV_UP, so we need to reset it. The check for
|
* ipv6 mtu on NETDEV_UP, so we need to reset it. The check for
|
||||||
* ipv6_mtu_set prevents this from trying to set it too early before
|
* ipv6_mtu_set prevents this from trying to set it too early before
|
||||||
@ -2672,6 +2704,21 @@ static int link_admin_state_up(Link *link) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int link_admin_state_down(Link *link) {
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
|
||||||
|
if (!link->network)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
|
||||||
|
log_link_info(link, "ActivationPolicy is \"always-on\", forcing link up");
|
||||||
|
return link_up(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int link_update(Link *link, sd_netlink_message *m) {
|
int link_update(Link *link, sd_netlink_message *m) {
|
||||||
_cleanup_strv_free_ char **s = NULL;
|
_cleanup_strv_free_ char **s = NULL;
|
||||||
hw_addr_data hw_addr;
|
hw_addr_data hw_addr;
|
||||||
@ -2784,9 +2831,14 @@ int link_update(Link *link, sd_netlink_message *m) {
|
|||||||
r = link_admin_state_up(link);
|
r = link_admin_state_up(link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
} else if (link_was_admin_up && !(link->flags & IFF_UP))
|
} else if (link_was_admin_up && !(link->flags & IFF_UP)) {
|
||||||
log_link_info(link, "Link DOWN");
|
log_link_info(link, "Link DOWN");
|
||||||
|
|
||||||
|
r = link_admin_state_down(link);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
r = link_update_lldp(link);
|
r = link_update_lldp(link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -129,6 +129,7 @@ typedef struct Link {
|
|||||||
bool setting_genmode:1;
|
bool setting_genmode:1;
|
||||||
bool ipv6_mtu_set:1;
|
bool ipv6_mtu_set:1;
|
||||||
bool bridge_mdb_configured:1;
|
bool bridge_mdb_configured:1;
|
||||||
|
bool activated:1;
|
||||||
|
|
||||||
sd_dhcp_server *dhcp_server;
|
sd_dhcp_server *dhcp_server;
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ Link.Multicast, config_parse_tristate,
|
|||||||
Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast)
|
Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast)
|
||||||
Link.Promiscuous, config_parse_tristate, 0, offsetof(Network, promiscuous)
|
Link.Promiscuous, config_parse_tristate, 0, offsetof(Network, promiscuous)
|
||||||
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
|
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
|
||||||
|
Link.ActivationPolicy, config_parse_activation_policy, 0, offsetof(Network, activation_policy)
|
||||||
Link.RequiredForOnline, config_parse_required_for_online, 0, 0
|
Link.RequiredForOnline, config_parse_required_for_online, 0, 0
|
||||||
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, 0
|
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, 0
|
||||||
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, 0
|
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, 0
|
||||||
|
@ -225,9 +225,6 @@ int network_verify(Network *network) {
|
|||||||
if (network->dhcp_use_gateway < 0)
|
if (network->dhcp_use_gateway < 0)
|
||||||
network->dhcp_use_gateway = network->dhcp_use_routes;
|
network->dhcp_use_gateway = network->dhcp_use_routes;
|
||||||
|
|
||||||
if (network->ignore_carrier_loss < 0)
|
|
||||||
network->ignore_carrier_loss = network->configure_without_carrier;
|
|
||||||
|
|
||||||
if (network->dhcp_critical >= 0) {
|
if (network->dhcp_critical >= 0) {
|
||||||
if (network->keep_configuration >= 0)
|
if (network->keep_configuration >= 0)
|
||||||
log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
|
log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
|
||||||
@ -239,6 +236,30 @@ int network_verify(Network *network) {
|
|||||||
network->keep_configuration = KEEP_CONFIGURATION_NO;
|
network->keep_configuration = KEEP_CONFIGURATION_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strv_isempty(network->bind_carrier)) {
|
||||||
|
if (!IN_SET(network->activation_policy, _ACTIVATION_POLICY_INVALID, ACTIVATION_POLICY_BOUND))
|
||||||
|
log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
|
||||||
|
"Setting ActivationPolicy=bound.", network->filename);
|
||||||
|
network->activation_policy = ACTIVATION_POLICY_BOUND;
|
||||||
|
} else if (network->activation_policy == ACTIVATION_POLICY_BOUND) {
|
||||||
|
log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
|
||||||
|
"Ignoring ActivationPolicy=bound.", network->filename);
|
||||||
|
network->activation_policy = ACTIVATION_POLICY_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (network->activation_policy == _ACTIVATION_POLICY_INVALID)
|
||||||
|
network->activation_policy = ACTIVATION_POLICY_UP;
|
||||||
|
|
||||||
|
if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
|
||||||
|
if (network->ignore_carrier_loss == false)
|
||||||
|
log_warning("%s: IgnoreCarrierLoss=false conflicts with ActivationPolicy=always-up. "
|
||||||
|
"Setting IgnoreCarrierLoss=true.", network->filename);
|
||||||
|
network->ignore_carrier_loss = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (network->ignore_carrier_loss < 0)
|
||||||
|
network->ignore_carrier_loss = network->configure_without_carrier;
|
||||||
|
|
||||||
if (network->keep_configuration < 0)
|
if (network->keep_configuration < 0)
|
||||||
network->keep_configuration = KEEP_CONFIGURATION_NO;
|
network->keep_configuration = KEEP_CONFIGURATION_NO;
|
||||||
|
|
||||||
@ -316,6 +337,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||||||
|
|
||||||
.required_for_online = true,
|
.required_for_online = true,
|
||||||
.required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
|
.required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
|
||||||
|
.activation_policy = _ACTIVATION_POLICY_INVALID,
|
||||||
.arp = -1,
|
.arp = -1,
|
||||||
.multicast = -1,
|
.multicast = -1,
|
||||||
.allmulticast = -1,
|
.allmulticast = -1,
|
||||||
@ -1247,3 +1269,15 @@ static const char* const ipv6_link_local_address_gen_mode_table[_IPV6_LINK_LOCAL
|
|||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode);
|
DEFINE_STRING_TABLE_LOOKUP(ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode);
|
||||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_link_local_address_gen_mode, ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode, "Failed to parse IPv6 link local address generation mode");
|
DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_link_local_address_gen_mode, ipv6_link_local_address_gen_mode, IPv6LinkLocalAddressGenMode, "Failed to parse IPv6 link local address generation mode");
|
||||||
|
|
||||||
|
static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = {
|
||||||
|
[ACTIVATION_POLICY_UP] = "up",
|
||||||
|
[ACTIVATION_POLICY_ALWAYS_UP] = "always-up",
|
||||||
|
[ACTIVATION_POLICY_MANUAL] = "manual",
|
||||||
|
[ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down",
|
||||||
|
[ACTIVATION_POLICY_DOWN] = "down",
|
||||||
|
[ACTIVATION_POLICY_BOUND] = "bound",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
|
||||||
|
DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy, "Failed to parse activation policy");
|
||||||
|
@ -47,6 +47,17 @@ typedef enum IPv6LinkLocalAddressGenMode {
|
|||||||
_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID = -1
|
_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID = -1
|
||||||
} IPv6LinkLocalAddressGenMode;
|
} IPv6LinkLocalAddressGenMode;
|
||||||
|
|
||||||
|
typedef enum ActivationPolicy {
|
||||||
|
ACTIVATION_POLICY_UP,
|
||||||
|
ACTIVATION_POLICY_ALWAYS_UP,
|
||||||
|
ACTIVATION_POLICY_MANUAL,
|
||||||
|
ACTIVATION_POLICY_ALWAYS_DOWN,
|
||||||
|
ACTIVATION_POLICY_DOWN,
|
||||||
|
ACTIVATION_POLICY_BOUND,
|
||||||
|
_ACTIVATION_POLICY_MAX,
|
||||||
|
_ACTIVATION_POLICY_INVALID = -1
|
||||||
|
} ActivationPolicy;
|
||||||
|
|
||||||
typedef struct Manager Manager;
|
typedef struct Manager Manager;
|
||||||
|
|
||||||
typedef struct NetworkDHCPServerEmitAddress {
|
typedef struct NetworkDHCPServerEmitAddress {
|
||||||
@ -93,6 +104,7 @@ struct Network {
|
|||||||
bool unmanaged;
|
bool unmanaged;
|
||||||
bool required_for_online; /* Is this network required to be considered online? */
|
bool required_for_online; /* Is this network required to be considered online? */
|
||||||
LinkOperationalStateRange required_operstate_for_online;
|
LinkOperationalStateRange required_operstate_for_online;
|
||||||
|
ActivationPolicy activation_policy;
|
||||||
|
|
||||||
/* misc settings */
|
/* misc settings */
|
||||||
bool configure_without_carrier;
|
bool configure_without_carrier;
|
||||||
@ -334,6 +346,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
|
|||||||
CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
|
CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode);
|
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_rx_tx_queues);
|
CONFIG_PARSER_PROTOTYPE(config_parse_rx_tx_queues);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy);
|
||||||
|
|
||||||
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||||
|
|
||||||
@ -342,3 +355,6 @@ KeepConfiguration keep_configuration_from_string(const char *s) _pure_;
|
|||||||
|
|
||||||
const char* ipv6_link_local_address_gen_mode_to_string(IPv6LinkLocalAddressGenMode s) _const_;
|
const char* ipv6_link_local_address_gen_mode_to_string(IPv6LinkLocalAddressGenMode s) _const_;
|
||||||
IPv6LinkLocalAddressGenMode ipv6_link_local_address_gen_mode_from_string(const char *s) _pure_;
|
IPv6LinkLocalAddressGenMode ipv6_link_local_address_gen_mode_from_string(const char *s) _pure_;
|
||||||
|
|
||||||
|
const char* activation_policy_to_string(ActivationPolicy i) _const_;
|
||||||
|
ActivationPolicy activation_policy_from_string(const char *s) _pure_;
|
||||||
|
@ -30,6 +30,7 @@ Host=
|
|||||||
MACAddress=
|
MACAddress=
|
||||||
PermanentMACAddress=
|
PermanentMACAddress=
|
||||||
[Link]
|
[Link]
|
||||||
|
ActivationPolicy=
|
||||||
RequiredForOnline=
|
RequiredForOnline=
|
||||||
ARP=
|
ARP=
|
||||||
AllMulticast=
|
AllMulticast=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user