From: Shihao Ren Date: Fri, 10 Jul 2026 07:26:27 +0000 (+0800) Subject: network: do not regenerate MAC address if already set by userspace X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dbb59dab734238aa3fb6caa27ca7c12bdeb461b4;p=thirdparty%2Fsystemd.git network: do not regenerate MAC address if already set by userspace When MACAddress= is unspecified, a stable MAC is generated to seed a newly created netdev. Since existing netdevs are reconfigured on reload/restart, this seed got re-applied to an already existing interface, conflicting with an explicit MACAddress= from the matching .network file and flipping MAC. Now, when MACAddress= is unspecified, only generate a new address if addr_assign_type is not NET_ADDR_SET (i.e. not already set by userspace). On first creation the interface does not exist yet, so this is a no-op and the address is generated as before. Mirrors src/udev/net/link-config.c. Fixes: #42457 --- diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 658eb1808f1..74b036a7ad5 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include +#include #include #include "sd-netlink.h" @@ -14,6 +15,7 @@ #include "condition.h" #include "conf-files.h" #include "conf-parser.h" +#include "device-private.h" #include "dummy.h" #include "fou-tunnel.h" #include "geneve.h" @@ -575,6 +577,21 @@ int netdev_generate_hw_addr( if (!IN_SET(NETDEV_VTABLE(netdev)->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND)) goto finalize; + /* If the interface already exists and its MAC address has been set by userspace + * (e.g. through MACAddress= in the matching .network file, or manually), do not + * generate a new address. Otherwise, on reconfiguration the generated address would + * override the one set by userspace and, as they differ, both would be re-applied on + * every reload/restart. See issue #42457. */ + Link *link; + unsigned addr_assign_type; + if (link_get_by_index(netdev->manager, netdev->ifindex, &link) >= 0 && + link->dev && + device_get_sysattr_unsigned(link->dev, "addr_assign_type", &addr_assign_type) >= 0 && + addr_assign_type == NET_ADDR_SET) { + log_netdev_debug(netdev, "MAC address is already set by userspace, not generating a new one."); + goto finalize; + } + r = net_get_unique_predictable_data_from_name(name, &HASH_KEY, &result); if (r < 0) { log_netdev_warning_errno(netdev, r, @@ -964,6 +981,13 @@ static int independent_netdev_process_request(Request *req, Link *link, void *us return 1; /* Skip this request. */ } + Link *existing; + if (link_get_by_index(netdev->manager, netdev->ifindex, &existing) >= 0 && + IN_SET(existing->state, + LINK_STATE_PENDING, /* Already exists and is being processed by udevd. Postpone the request. */ + LINK_STATE_LINGER)) /* Already removed; wait for the stale information to be cleared. */ + return 0; + r = netdev_is_ready_to_create(netdev, NULL); if (r <= 0) return r;