mirror of
https://github.com/systemd/systemd.git
synced 2024-12-03 23:33:38 +08:00
Merge pull request #21344 from yuwata/network-ignore-carrier-loss-timespan
network: make IgnoreCarrierLoss= also take a timespan
This commit is contained in:
commit
7777024dab
@ -952,18 +952,21 @@ Table=1234</programlisting></para>
|
||||
<term><varname>ConfigureWithoutCarrier=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. Allows networkd to configure a specific link even if it has no carrier.
|
||||
Defaults to false. If <option>IgnoreCarrierLoss=</option> is not explicitly set, it will
|
||||
default to this value.
|
||||
Defaults to false. If enabled, and the <varname>IgnoreCarrierLoss=</varname> setting is not
|
||||
explicitly set, then it is enabled as well.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>IgnoreCarrierLoss=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. Allows networkd to retain both the static and dynamic configuration
|
||||
of the interface even if its carrier is lost. When unset, the value specified with
|
||||
<option>ConfigureWithoutCarrier=</option> is used.
|
||||
</para>
|
||||
<para>Takes a boolean or a timespan. When true, networkd retains both the static and dynamic
|
||||
configuration of the interface even if its carrier is lost. When a timespan is specified,
|
||||
networkd waits for the specified timespan, and ignores the carrier loss if the link regain
|
||||
its carrier within the timespan. Setting a finite timespan may be useful for a wireless
|
||||
interface connecting to a network which has multiple access points with the same SSID, or an
|
||||
interface which is reset on changing MTU. When unset, the value specified with
|
||||
<varname>ConfigureWithoutCarrier=</varname> is used.</para>
|
||||
|
||||
<para>When <varname>ActivationPolicy=</varname> is set to <literal>always-up</literal>, this
|
||||
is forced to <literal>true</literal>.
|
||||
@ -1813,6 +1816,9 @@ Table=1234</programlisting></para>
|
||||
<para>When true, the interface maximum transmission unit from the DHCP server will be used on the
|
||||
current link. If <varname>MTUBytes=</varname> is set, then this setting is ignored. Defaults to
|
||||
false.</para>
|
||||
<para>Note, some drivers will reset the interfaces if the MTU is changed. For such
|
||||
interfaces, please try to use <varname>IgnoreCarrierLoss=</varname> with a short timespan,
|
||||
e.g. <literal>3 seconds</literal>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -84,6 +84,30 @@ int event_reset_time(
|
||||
return created;
|
||||
}
|
||||
|
||||
int event_reset_time_relative(
|
||||
sd_event *e,
|
||||
sd_event_source **s,
|
||||
clockid_t clock,
|
||||
uint64_t usec,
|
||||
uint64_t accuracy,
|
||||
sd_event_time_handler_t callback,
|
||||
void *userdata,
|
||||
int64_t priority,
|
||||
const char *description,
|
||||
bool force_reset) {
|
||||
|
||||
usec_t usec_now;
|
||||
int r;
|
||||
|
||||
assert(e);
|
||||
|
||||
r = sd_event_now(e, clock, &usec_now);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "sd-event: Failed to get the current time: %m");
|
||||
|
||||
return event_reset_time(e, s, clock, usec_add(usec_now, usec), accuracy, callback, userdata, priority, description, force_reset);
|
||||
}
|
||||
|
||||
int event_source_disable(sd_event_source *s) {
|
||||
if (!s)
|
||||
return 0;
|
||||
|
@ -5,9 +5,27 @@
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
int event_reset_time(sd_event *e, sd_event_source **s,
|
||||
clockid_t clock, uint64_t usec, uint64_t accuracy,
|
||||
sd_event_time_handler_t callback, void *userdata,
|
||||
int64_t priority, const char *description, bool force_reset);
|
||||
int event_reset_time(
|
||||
sd_event *e,
|
||||
sd_event_source **s,
|
||||
clockid_t clock,
|
||||
uint64_t usec,
|
||||
uint64_t accuracy,
|
||||
sd_event_time_handler_t callback,
|
||||
void *userdata,
|
||||
int64_t priority,
|
||||
const char *description,
|
||||
bool force_reset);
|
||||
int event_reset_time_relative(
|
||||
sd_event *e,
|
||||
sd_event_source **s,
|
||||
clockid_t clock,
|
||||
uint64_t usec,
|
||||
uint64_t accuracy,
|
||||
sd_event_time_handler_t callback,
|
||||
void *userdata,
|
||||
int64_t priority,
|
||||
const char *description,
|
||||
bool force_reset);
|
||||
int event_source_disable(sd_event_source *s);
|
||||
int event_source_is_enabled(sd_event_source *s);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "dhcp-lease-internal.h"
|
||||
#include "env-file.h"
|
||||
#include "ethtool-util.h"
|
||||
#include "event-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "format-util.h"
|
||||
@ -244,6 +245,7 @@ static Link *link_free(Link *link) {
|
||||
strv_free(link->alternative_names);
|
||||
free(link->kind);
|
||||
free(link->ssid);
|
||||
free(link->previous_ssid);
|
||||
free(link->driver);
|
||||
|
||||
unlink_and_free(link->lease_file);
|
||||
@ -259,6 +261,8 @@ static Link *link_free(Link *link) {
|
||||
|
||||
network_unref(link->network);
|
||||
|
||||
sd_event_source_disable_unref(link->carrier_lost_timer);
|
||||
|
||||
return mfree(link);
|
||||
}
|
||||
|
||||
@ -1581,10 +1585,34 @@ int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, voi
|
||||
}
|
||||
|
||||
static int link_carrier_gained(Link *link) {
|
||||
bool force_reconfigure;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
r = event_source_disable(link->carrier_lost_timer);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to disable carrier lost timer, ignoring: %m");
|
||||
|
||||
/* If the SSID is changed, then the connected wireless network could be changed. So, always
|
||||
* reconfigure the link. Which means e.g. the DHCP client will be restarted, and the correct
|
||||
* network information will be gained.
|
||||
* For non-wireless interfaces, we have no way to detect the connected network change. So,
|
||||
* setting force_reconfigure = false. Note, both ssid and previous_ssid should be NULL for
|
||||
* non-wireless interfaces, and streq_ptr() returns true. */
|
||||
force_reconfigure = !streq_ptr(link->previous_ssid, link->ssid);
|
||||
link->previous_ssid = mfree(link->previous_ssid);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
|
||||
/* At this stage, both wlan and link information should be up-to-date. Hence,
|
||||
* it is not necessary to call RTM_GETLINK, NL80211_CMD_GET_INTERFACE, or
|
||||
* NL80211_CMD_GET_STATION commands, and simply call link_reconfigure_impl().
|
||||
* Note, link_reconfigure_impl() returns 1 when the link is reconfigured. */
|
||||
r = link_reconfigure_impl(link, force_reconfigure);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1606,6 +1634,45 @@ static int link_carrier_gained(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_carrier_lost_impl(Link *link) {
|
||||
int r, ret = 0;
|
||||
|
||||
assert(link);
|
||||
|
||||
link->previous_ssid = mfree(link->previous_ssid);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
if (!link->network)
|
||||
return 0;
|
||||
|
||||
r = link_stop_engines(link, false);
|
||||
if (r < 0)
|
||||
ret = r;
|
||||
|
||||
r = link_drop_config(link);
|
||||
if (r < 0 && ret >= 0)
|
||||
ret = r;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int link_carrier_lost_handler(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
Link *link = userdata;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
r = link_carrier_lost_impl(link);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to process carrier lost event: %m");
|
||||
link_enter_failed(link);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_carrier_lost(Link *link) {
|
||||
int r;
|
||||
|
||||
@ -1622,16 +1689,22 @@ static int link_carrier_lost(Link *link) {
|
||||
if (!link->network)
|
||||
return 0;
|
||||
|
||||
if (link->network->ignore_carrier_loss)
|
||||
if (link->network->ignore_carrier_loss_usec == USEC_INFINITY)
|
||||
return 0;
|
||||
|
||||
r = link_stop_engines(link, false);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
if (link->network->ignore_carrier_loss_usec == 0)
|
||||
return link_carrier_lost_impl(link);
|
||||
|
||||
return link_drop_config(link);
|
||||
return event_reset_time_relative(link->manager->event,
|
||||
&link->carrier_lost_timer,
|
||||
clock_boottime_or_monotonic(),
|
||||
link->network->ignore_carrier_loss_usec,
|
||||
0,
|
||||
link_carrier_lost_handler,
|
||||
link,
|
||||
0,
|
||||
"link-carrier-loss",
|
||||
true);
|
||||
}
|
||||
|
||||
static int link_admin_state_up(Link *link) {
|
||||
@ -1958,15 +2031,6 @@ static int link_update_flags(Link *link, sd_netlink_message *message) {
|
||||
if (!had_carrier && link_has_carrier(link)) {
|
||||
log_link_info(link, "Gained carrier");
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
|
||||
/* At this stage, both wlan and link information should be up-to-date. Hence,
|
||||
* it is not necessary to call RTM_GETLINK, NL80211_CMD_GET_INTERFACE, or
|
||||
* NL80211_CMD_GET_STATION commands, and simply call link_reconfigure_impl(). */
|
||||
r = link_reconfigure_impl(link, /* force = */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = link_carrier_gained(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -67,11 +67,14 @@ typedef struct Link {
|
||||
/* wlan */
|
||||
enum nl80211_iftype wlan_iftype;
|
||||
char *ssid;
|
||||
char *previous_ssid;
|
||||
struct ether_addr bssid;
|
||||
|
||||
unsigned flags;
|
||||
uint8_t kernel_operstate;
|
||||
|
||||
sd_event_source *carrier_lost_timer;
|
||||
|
||||
Network *network;
|
||||
|
||||
LinkState state;
|
||||
|
@ -135,7 +135,7 @@ Network.ProxyARP, config_parse_tristate,
|
||||
Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0
|
||||
Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
|
||||
Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier)
|
||||
Network.IgnoreCarrierLoss, config_parse_tristate, 0, offsetof(Network, ignore_carrier_loss)
|
||||
Network.IgnoreCarrierLoss, config_parse_ignore_carrier_loss, 0, 0
|
||||
Network.KeepConfiguration, config_parse_keep_configuration, 0, offsetof(Network, keep_configuration)
|
||||
Network.IPv6SendRA, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
|
||||
Network.DHCPv6PrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp6_pd)
|
||||
|
@ -271,14 +271,17 @@ int network_verify(Network *network) {
|
||||
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_set && network->ignore_carrier_loss_usec < USEC_INFINITY)
|
||||
log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
|
||||
"Setting IgnoreCarrierLoss=yes.", network->filename);
|
||||
network->ignore_carrier_loss_set = true;
|
||||
network->ignore_carrier_loss_usec = USEC_INFINITY;
|
||||
}
|
||||
|
||||
if (network->ignore_carrier_loss < 0)
|
||||
network->ignore_carrier_loss = network->configure_without_carrier;
|
||||
if (!network->ignore_carrier_loss_set) {
|
||||
network->ignore_carrier_loss_set = true;
|
||||
network->ignore_carrier_loss_usec = network->configure_without_carrier ? USEC_INFINITY : 0;
|
||||
}
|
||||
|
||||
if (IN_SET(network->activation_policy, ACTIVATION_POLICY_DOWN, ACTIVATION_POLICY_ALWAYS_DOWN, ACTIVATION_POLICY_MANUAL)) {
|
||||
if (network->required_for_online < 0 ||
|
||||
@ -379,7 +382,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
.allmulticast = -1,
|
||||
.promiscuous = -1,
|
||||
|
||||
.ignore_carrier_loss = -1,
|
||||
.keep_configuration = _KEEP_CONFIGURATION_INVALID,
|
||||
|
||||
.dhcp_duid.type = _DUID_TYPE_INVALID,
|
||||
@ -1285,6 +1287,51 @@ int config_parse_link_group(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_ignore_carrier_loss(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Network *network = userdata;
|
||||
usec_t usec;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(network);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
network->ignore_carrier_loss_set = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = parse_boolean(rvalue);
|
||||
if (r >= 0) {
|
||||
network->ignore_carrier_loss_set = true;
|
||||
network->ignore_carrier_loss_usec = r > 0 ? USEC_INFINITY : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = parse_sec(rvalue, &usec);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
network->ignore_carrier_loss_set = true;
|
||||
network->ignore_carrier_loss_usec = usec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily,
|
||||
"Failed to parse RequiredFamilyForOnline= setting");
|
||||
|
||||
|
@ -109,7 +109,8 @@ struct Network {
|
||||
|
||||
/* misc settings */
|
||||
bool configure_without_carrier;
|
||||
int ignore_carrier_loss;
|
||||
bool ignore_carrier_loss_set;
|
||||
usec_t ignore_carrier_loss_usec; /* timespan */
|
||||
KeepConfiguration keep_configuration;
|
||||
char **bind_carrier;
|
||||
bool default_route_on_device;
|
||||
@ -383,6 +384,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_link_group);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ignore_carrier_loss);
|
||||
|
||||
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||
|
||||
|
@ -273,7 +273,7 @@ int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *mess
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd);
|
||||
|
||||
link->bssid = ETHER_ADDR_NULL;
|
||||
link->ssid = mfree(link->ssid);
|
||||
free_and_replace(link->previous_ssid, link->ssid);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user