diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
index 69d8ee9b28..4caac11156 100644
--- a/man/systemd.net-naming-scheme.xml
+++ b/man/systemd.net-naming-scheme.xml
@@ -305,6 +305,21 @@
for a description of NamePolicy=.
+
+ v241
+
+ was extended to set MAC addresses
+ based on the device name. Previously addresses were only based on the
+ ID_NET_NAME_* attributes, which meant that interface names would
+ never be generated for virtual devices. Now a persistent address will be generated for most
+ devices, including in particular bridges.
+
+ Note: when userspace does not set a MAC address for a bridge device, the kernel will
+ initially assign a random address, and then change it when the first device is enslaved to the
+ bridge. With this naming policy change, bridges get a persistent MAC address based on the bridge
+ name instead of the first enslaved device.
+
+
v243
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 1a588f10d3..9a1b2fba89 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -39,7 +39,7 @@ const char *net_get_name_persistent(sd_device *device) {
#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
-int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
+int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result) {
size_t l, sz = 0;
const char *name;
int r;
@@ -50,7 +50,7 @@ int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
/* net_get_name_persistent() will return one of the device names based on stable information about
* the device. If this is not available, we fall back to using the actual device name. */
name = net_get_name_persistent(device);
- if (!name)
+ if (!name && use_sysname)
(void) sd_device_get_sysname(device, &name);
if (!name)
return log_device_debug_errno(device, SYNTHETIC_ERRNO(ENODATA),
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index bb2bd8b35b..ebfb1c3c75 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -32,7 +32,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
-int net_get_unique_predictable_data(sd_device *device, uint64_t *result);
+int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result);
const char *net_get_name_persistent(sd_device *device);
size_t serialize_in_addrs(FILE *f,
diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c
index 9df5646a7e..738d22cb5b 100644
--- a/src/network/networkd-ipv4ll.c
+++ b/src/network/networkd-ipv4ll.c
@@ -210,7 +210,7 @@ int ipv4ll_configure(Link *link) {
}
if (link->sd_device &&
- net_get_unique_predictable_data(link->sd_device, &seed) >= 0) {
+ net_get_unique_predictable_data(link->sd_device, true, &seed) >= 0) {
r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
if (r < 0)
return r;
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index a4e10ff988..b983f28f2f 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -318,10 +318,13 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr
} else {
uint64_t result;
- r = net_get_unique_predictable_data(device, &result);
+ r = net_get_unique_predictable_data(device,
+ naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS),
+ &result);
if (r < 0)
return log_device_warning_errno(device, r, "Could not generate persistent MAC: %m");
+ log_device_debug(device, "Using generated persistent MAC address");
assert_cc(ETH_ALEN <= sizeof(result));
memcpy(mac->ether_addr_octet, &result, ETH_ALEN);
}
diff --git a/src/udev/net/naming-scheme.c b/src/udev/net/naming-scheme.c
index 8223f9cda1..0d7f413e9e 100644
--- a/src/udev/net/naming-scheme.c
+++ b/src/udev/net/naming-scheme.c
@@ -8,6 +8,7 @@ static const NamingScheme naming_schemes[] = {
{ "v238", NAMING_V238 },
{ "v239", NAMING_V239 },
{ "v240", NAMING_V240 },
+ { "v241", NAMING_V241 },
{ "v243", NAMING_V243 },
/* … add more schemes here, as the logic to name devices is updated … */
};
diff --git a/src/udev/net/naming-scheme.h b/src/udev/net/naming-scheme.h
index 584fea876c..38dfa75f9b 100644
--- a/src/udev/net/naming-scheme.h
+++ b/src/udev/net/naming-scheme.h
@@ -27,14 +27,16 @@ typedef enum NamingSchemeFlags {
NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df */
NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Use zero acpi_index field, see d81186ef4f6a */
NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */
- NAMING_NETDEVSIM = 1 << 5, /* Generate names for netdevsim devices, see eaa9d507d855 */
- NAMING_LABEL_NOPREFIX = 1 << 6, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */
+ NAMING_STABLE_VIRTUAL_MACS = 1 << 5, /* Use device name to generate MAC, see 6d3646406560 */
+ NAMING_NETDEVSIM = 1 << 6, /* Generate names for netdevsim devices, see eaa9d507d855 */
+ NAMING_LABEL_NOPREFIX = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
NAMING_V239 = NAMING_V238 | NAMING_SR_IOV_V | NAMING_NPAR_ARI,
NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
- NAMING_V243 = NAMING_V240 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
+ NAMING_V241 = NAMING_V240 | NAMING_STABLE_VIRTUAL_MACS,
+ NAMING_V243 = NAMING_V241 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
_NAMING_SCHEME_FLAGS_INVALID = -1,
} NamingSchemeFlags;