From 1747eb96d6f3285b1cc2b4ec2b1be7ef7b35c1c4 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Thu, 19 Mar 2026 15:42:47 +0800 Subject: [PATCH] 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);