From 09784fcce3ce4afb4b9d1f8c7352406156bcf6c2 Mon Sep 17 00:00:00 2001 From: Rahul Rajesh Date: Mon, 20 Apr 2026 16:23:20 -0400 Subject: [PATCH 1/2] device: cleanup DHCP before devices removed Add _dev_ipdhcpx_cleanup in __set_state_full in DEACTIVATING STATE before STATE_CHANGED signal is emitted to ensure DHCP RELEASE packet is sent. Assisted-by: Cursor with Claude Opus 4.5 --- src/core/devices/nm-device.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index f8b0dad9c8..6e9b04b34f 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -17980,6 +17980,14 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, nm_device_cleanup(self, reason, CLEANUP_TYPE_DECONFIGURE); } break; + case NM_DEVICE_STATE_DEACTIVATING: + /* When deactivating, certain devices are removed/disconnected after the + * STATE_CHANGED signal is sent and before the DHCP release packet + * can be sent. To ensure the release packet is sent, we cleanup DHCP + * before the signal is emitted*/ + _dev_ipdhcpx_cleanup(self, AF_INET, TRUE, FALSE); + _dev_ipdhcpx_cleanup(self, AF_INET6, TRUE, FALSE); + break; case NM_DEVICE_STATE_DISCONNECTED: if (old_state > NM_DEVICE_STATE_DISCONNECTED) { /* Ensure devices that previously assumed a connection now have @@ -18029,6 +18037,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, (guint32) state, (guint32) old_state, (guint32) reason); + g_signal_emit(self, signals[STATE_CHANGED], 0, From 1747eb96d6f3285b1cc2b4ec2b1be7ef7b35c1c4 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Thu, 19 Mar 2026 15:42:47 +0800 Subject: [PATCH 2/2] manager: Ensure DHCP interface delete first when daemon stop Given linux bridge/bond holds DHCP config with `ipv4.dhcp-send-release: ture` or `ipv6.dhcp-send-release: true`, when stopping NetworkManager daemon, then NM daemon might remove/deactivate physical interface first causing DHCP release packet cannot be delivered. To fix the issue, we sort the device deletion to let software device that holds DHCP config to remove first. Merge Request: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2379 Co-authored-by: Rahul Rajesh --- src/core/nm-manager.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 87dde2c3af..ada26de1bd 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -8146,6 +8146,27 @@ nm_manager_start(NMManager *self, GError **error) return TRUE; } +static int +compare_device_remove_order(const CList *a, const CList *b, const void *user_data) +{ + NMDevice *dev_a = c_list_entry(a, NMDevice, devices_lst); + NMDevice *dev_b = c_list_entry(b, NMDevice, devices_lst); + + gboolean a_has_dhcp = + nm_device_get_dhcp_config(dev_a, AF_INET) || nm_device_get_dhcp_config(dev_a, AF_INET6); + gboolean b_has_dhcp = + nm_device_get_dhcp_config(dev_b, AF_INET) || nm_device_get_dhcp_config(dev_b, AF_INET6); + gboolean a_is_software = nm_device_is_software(dev_a); + gboolean b_is_software = nm_device_is_software(dev_b); + + /* priority: software AND dhcp first, then dhcp only + * then everything else,*/ + uint a_score = a_has_dhcp ? (a_is_software ? 2 : 1) : 0; + uint b_score = b_has_dhcp ? (b_is_software ? 2 : 1) : 0; + + return b_score - a_score; +} + void nm_manager_stop(NMManager *self) { @@ -8167,6 +8188,12 @@ nm_manager_stop(NMManager *self) nm_dbus_manager_stop(nm_dbus_object_get_manager(NM_DBUS_OBJECT(self))); + /* When OVS internal interface or linux bridge holds DHCP, if we delete its + * physical interface first, then we cannot send out DHCP release request + * anymore. To fix that, we need to remove/deactivate software interfaces that + * holds DHCP config first. + */ + c_list_sort(&priv->devices_lst_head, compare_device_remove_order, NULL); while ((device = c_list_first_entry(&priv->devices_lst_head, NMDevice, devices_lst))) remove_device(self, device, TRUE);