]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: also check ID_NET_MANAGED_BY property on reconfigure
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 11 Jun 2025 09:05:46 +0000 (18:05 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 12 Jun 2025 05:24:50 +0000 (14:24 +0900)
Previously, the property was checked only when an uevent is received,
so even if an interface has ID_NET_MANAGED_BY property, the interface
will be configured by networkd when reconfiguration is triggered e.g.
when interface state is changed.

Follow-up for ba87a61d05d637be9f0b21707f7fe3b0a74c5a05.
Fixes #36997.

src/network/networkd-link.c
test/test-network/conf/11-dummy-unmanaged.link [new file with mode: 0644]
test/test-network/systemd-networkd-tests.py

index 65fd8b43e3b52b490f2b4216214f6402ed5bfe2a..4f7e1a15525a8a885f6170728c827ea37840910e 100644 (file)
@@ -1369,6 +1369,32 @@ static void link_enter_unmanaged(Link *link) {
         link_set_state(link, LINK_STATE_UNMANAGED);
 }
 
+static int link_managed_by_us(Link *link) {
+        int r;
+
+        assert(link);
+
+        if (!link->dev)
+                return true;
+
+        const char *s;
+        r = sd_device_get_property_value(link->dev, "ID_NET_MANAGED_BY", &s);
+        if (r == -ENOENT)
+                return true;
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to get ID_NET_MANAGED_BY udev property: %m");
+
+        if (streq(s, "io.systemd.Network"))
+                return true;
+
+        if (link->state == LINK_STATE_UNMANAGED)
+                return false; /* Already in unmanaged state */
+
+        log_link_debug(link, "Interface is requested to be managed by '%s', unmanaging the interface.", s);
+        link_set_state(link, LINK_STATE_UNMANAGED);
+        return false;
+}
+
 int link_reconfigure_impl(Link *link, LinkReconfigurationFlag flags) {
         Network *network = NULL;
         int r;
@@ -1384,6 +1410,10 @@ int link_reconfigure_impl(Link *link, LinkReconfigurationFlag flags) {
         if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
                 return 0;
 
+        r = link_managed_by_us(link);
+        if (r <= 0)
+                return r;
+
         r = link_get_network(link, &network);
         if (r == -ENOENT) {
                 link_enter_unmanaged(link);
@@ -1621,6 +1651,10 @@ static int link_initialized(Link *link, sd_device *device) {
          * or sysattrs) may be outdated. */
         device_unref_and_replace(link->dev, device);
 
+        r = link_managed_by_us(link);
+        if (r <= 0)
+                return r;
+
         if (link->dhcp_client) {
                 r = sd_dhcp_client_attach_device(link->dhcp_client, link->dev);
                 if (r < 0)
@@ -1688,7 +1722,6 @@ int link_check_initialized(Link *link) {
 
 int manager_udev_process_link(Manager *m, sd_device *device, sd_device_action_t action) {
         int r, ifindex;
-        const char *s;
         Link *link;
 
         assert(m);
@@ -1723,15 +1756,6 @@ int manager_udev_process_link(Manager *m, sd_device *device, sd_device_action_t
                 return 0;
         }
 
-        r = sd_device_get_property_value(device, "ID_NET_MANAGED_BY", &s);
-        if (r < 0 && r != -ENOENT)
-                log_device_debug_errno(device, r, "Failed to get ID_NET_MANAGED_BY udev property, ignoring: %m");
-        if (r >= 0 && !streq(s, "io.systemd.Network")) {
-                log_device_debug(device, "Interface is requested to be managed by '%s', not managing the interface.", s);
-                link_set_state(link, LINK_STATE_UNMANAGED);
-                return 0;
-        }
-
         r = link_initialized(link, device);
         if (r < 0)
                 link_enter_failed(link);
diff --git a/test/test-network/conf/11-dummy-unmanaged.link b/test/test-network/conf/11-dummy-unmanaged.link
new file mode 100644 (file)
index 0000000..99c07a7
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: MIT-0
+[Match]
+Kind=dummy
+OriginalName=test1
+
+[Link]
+NamePolicy=keep
+Property=ID_NET_MANAGED_BY=hoge
index 8ecae739664fe394d8f3d0f08d8462b231861a7c..91e51ba1426b6ef3e5caea5ded04ca3902c8229c 100755 (executable)
@@ -3397,6 +3397,17 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
     def tearDown(self):
         tear_down_common()
 
+    def test_ID_NET_MANAGED_BY(self):
+        copy_network_unit('11-dummy.netdev', '11-dummy-unmanaged.link', '11-dummy.network')
+        start_networkd()
+        self.wait_online('test1:off', setup_state='unmanaged')
+
+        check_output('ip link set dev test1 up')
+        self.wait_online('test1:degraded', setup_state='unmanaged')
+
+        check_output('ip link set dev test1 down')
+        self.wait_online('test1:off', setup_state='unmanaged')
+
     def verify_address_static(
             self,
             label1: str,