network: automatically determine timeout of waiting for carrier regain

The commit 6706ce2fd2 made
IgnoreCarrierLoss= setting also take timespan, to make users handle
issues like #18738 or #20887. But still users needed to explicitly set
a timespan.

This makes networkd automatically determine the timeout when the
situations #18738 or #19832 is detected. Unfortunately, still users have
issue #20887 need to specify a value.

Closes #19832.
This commit is contained in:
Yu Watanabe 2022-03-30 00:52:09 +09:00
parent a14b9ca2c3
commit b732606950
2 changed files with 55 additions and 12 deletions

View file

@ -917,17 +917,36 @@ Table=1234</programlisting></para>
<varlistentry>
<term><varname>IgnoreCarrierLoss=</varname></term>
<listitem>
<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>Takes a boolean or a timespan. When true, <command>systemd-networkd</command> retains
both the static and dynamic configuration of the interface even if its carrier is lost. When
false, <command>systemd-networkd</command> drops both the static and dynamic configuration of
the interface. When a timespan is specified, <command>systemd-networkd</command> waits for
the specified timespan, and ignores the carrier loss if the link regain its carrier within
the timespan. Setting 0 seconds is equivalent to <literal>no</literal>, and
<literal>infinite</literal> is equivalent to <literal>yes</literal>.</para>
<para>When <varname>ActivationPolicy=</varname> is set to <literal>always-up</literal>, this
is forced to <literal>true</literal>.
<para>Setting a finite timespan may be useful when e.g. in the following cases:
<itemizedlist>
<listitem>
<para>A wireless interface connecting to a network which has multiple access points with
the same SSID.</para>
</listitem>
<listitem>
<para>Enslaving a wireless interface to a bond interface, which may disconnect from the
connected access point and causes its carrier to be lost.</para>
</listitem>
<listitem>
<para>The driver of the interface resets when the MTU is changed.</para>
</listitem>
</itemizedlist>
</para>
<para>When <varname>Bond=</varname> is specified to a wireless interface, defaults to 3
seconds. When the DHCPv4 client is enabled and <varname>UseMTU=</varname> in the [DHCPv4]
sectionis enabled, defaults to 5 seconds. Otherwise, defaults to the value specified with
<varname>ConfigureWithoutCarrier=</varname>. When <varname>ActivationPolicy=</varname> is set
to <literal>always-up</literal>, this is forced to <literal>yes</literal>, and ignored any
user specified values.</para>
</listitem>
</varlistentry>

View file

@ -1636,6 +1636,8 @@ static int link_carrier_lost_handler(sd_event_source *s, uint64_t usec, void *us
}
static int link_carrier_lost(Link *link) {
uint16_t dhcp_mtu;
usec_t usec;
int r;
assert(link);
@ -1651,16 +1653,38 @@ static int link_carrier_lost(Link *link) {
if (!link->network)
return 0;
if (link->network->ignore_carrier_loss_usec == USEC_INFINITY)
if (link->network->ignore_carrier_loss_set)
/* If IgnoreCarrierLoss= is explicitly specified, then use the specified value. */
usec = link->network->ignore_carrier_loss_usec;
else if (link->network->bond && link->wlan_iftype > 0)
/* Enslaving wlan interface to a bond disconnects from the connected AP, and causes its
* carrier to be lost. See #19832. */
usec = 3 * USEC_PER_SEC;
else if (link->network->dhcp_use_mtu &&
link->dhcp_lease &&
sd_dhcp_lease_get_mtu(link->dhcp_lease, &dhcp_mtu) >= 0 &&
dhcp_mtu != link->original_mtu)
/* Some drivers reset interfaces when changing MTU. Resetting interfaces by the static
* MTU should not cause any issues, as MTU is changed only once. However, setting MTU
* through DHCP lease causes an infinite loop of resetting the interface. See #18738. */
usec = 5 * USEC_PER_SEC;
else
/* Otherwise, use the currently set value. */
usec = link->network->ignore_carrier_loss_usec;
if (usec == USEC_INFINITY)
return 0;
if (link->network->ignore_carrier_loss_usec == 0)
if (usec == 0)
return link_carrier_lost_impl(link);
return event_reset_time_relative(link->manager->event,
&link->carrier_lost_timer,
CLOCK_BOOTTIME,
link->network->ignore_carrier_loss_usec,
usec,
0,
link_carrier_lost_handler,
link,