device: ensure DHCP is restarted every time the link goes up

Currently we call nm_device_update_dynamic_ip_setup() in
carrier_changed() every time the carrier goes up again and the device
is activating, to kick a restart of DHCP.

Since we process link events in a idle handler, it can happen that the
handler is called only once for different events; in particular
device_link_changed() might be called once for a link-down/link-up
sequence.

carrier_changed() is "level-triggered" - it cares only about the
current carrier state. nm_device_update_dynamic_ip_setup() should
instead be "edge-triggered" - invoked every time the link goes from
down to up. We have a mechanism for that in device_link_changed(), use
it.

Fixes-test: @ipv4_spurious_leftover_route

https://bugzilla.redhat.com/show_bug.cgi?id=2079406
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1250
This commit is contained in:
Beniamino Galvani
2022-06-06 15:43:05 +02:00
parent d15f5420c7
commit d6429d3ddb

View File

@@ -6276,10 +6276,6 @@ carrier_changed(NMDevice *self, gboolean carrier)
if (nm_device_is_master(self)) {
if (carrier) {
/* Force master to retry getting ip addresses when carrier
* is restored. */
if (priv->state == NM_DEVICE_STATE_ACTIVATED)
nm_device_update_dynamic_ip_setup(self);
/* If needed, also resume IP configuration that is
* waiting for carrier. */
if (priv->state == NM_DEVICE_STATE_IP_CONFIG)
@@ -6307,12 +6303,6 @@ carrier_changed(NMDevice *self, gboolean carrier)
* the device.
*/
nm_device_emit_recheck_auto_activate(self);
} else if (priv->state == NM_DEVICE_STATE_ACTIVATED) {
/* If the device is active without a carrier (probably because it is
* tagged for carrier ignore) ensure that when the carrier appears we
* renew DHCP leases and such.
*/
nm_device_update_dynamic_ip_setup(self);
}
} else {
if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) {
@@ -6700,6 +6690,14 @@ device_link_changed(gpointer user_data)
if (priv->state >= NM_DEVICE_STATE_IP_CONFIG && priv->state <= NM_DEVICE_STATE_ACTIVATED
&& !nm_device_sys_iface_state_is_external(self))
nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE);
/* If the device is active without a carrier (probably because it is
* tagged for carrier ignore) ensure that when the carrier appears we
* renew DHCP leases and such.
*/
if (priv->state == NM_DEVICE_STATE_ACTIVATED) {
nm_device_update_dynamic_ip_setup(self);
}
}
if (update_unmanaged_specs)