How to Dynamically Set Bridge MAC Address in systemd-networkd (Equivalent to ifupdown’s post-up)


2 views

When working with Linux bridges, maintaining a stable MAC address is crucial for network stability. In traditional /etc/network/interfaces configurations, we could use post-up hooks to dynamically set the bridge's MAC address based on a member interface:

post-up ip link set br0 address cat /sys/class/net/wlan0/address

This ensures each system maintains its unique MAC address (from wlan0) while preventing MAC flapping when adding interfaces with lower MAC addresses.

systemd-networkd handles post-configuration differently than ifupdown. Instead of direct command hooks, it uses a more structured approach through service units. Here are two methods to achieve dynamic MAC configuration:

Method 1: Using systemd-networkd Directives

For simple cases, you can use MACAddress= in your .netdev file:

[NetDev]
Name=br0
Kind=bridge
MACAddress=$(cat /sys/class/net/wlan0/address)

However, this requires environment variable expansion support which might not be available in all systemd versions.

Method 2: Creating a Custom Service Unit

For more control, create a service that runs after network configuration:

# /etc/systemd/system/set-bridge-mac.service
[Unit]
Description=Set bridge MAC address
After=sys-subsystem-net-devices-br0.device
BindsTo=sys-subsystem-net-devices-br0.device

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'ip link set br0 address $(cat /sys/class/net/wlan0/address)'

[Install]
WantedBy=multi-user.target

Then enable and start the service:

systemctl enable --now set-bridge-mac.service

For complex scenarios, consider networkd-dispatcher which provides hook-like functionality:

# /etc/networkd-dispatcher/routable.d/10-set-bridge-mac
#!/bin/sh
if [ "$IFACE" = "br0" ]; then
    ip link set br0 address $(cat /sys/class/net/wlan0/address)
fi

If your MAC address isn't persisting:

  • Check service dependencies with systemd-analyze verify set-bridge-mac.service
  • Verify timing with journalctl -u set-bridge-mac.service -b
  • Ensure proper device naming in /sys/class/net/

The service-based approach provides better integration with systemd's lifecycle management while maintaining the flexibility needed for dynamic network configuration.


When working with Linux bridges, maintaining a consistent MAC address is crucial for network stability. In traditional /etc/network/interfaces configurations, we'd use post-up commands to clone the MAC address from a physical interface:

# Traditional ifupdown approach
auto br0
iface br0 inet static
    bridge_ports eth0 wlan0
    post-up ip link set br0 address $(cat /sys/class/net/wlan0/address)

systemd-networkd handles this differently through its unit-based architecture. The equivalent functionality requires creating two unit files:

The NetDev Definition

# /etc/systemd/network/25-br0.netdev
[NetDev]
Name=br0
Kind=bridge

The Network Configuration

# /etc/systemd/network/25-br0.network
[Match]
Name=br0

[Network]
DHCP=no

To replicate the post-up functionality, we create a service unit that executes after the bridge is up:

# /etc/systemd/system/set-bridge-mac.service
[Unit]
Description=Set bridge MAC address
After=network.target sys-subsystem-net-devices-br0.device
Requires=sys-subsystem-net-devices-br0.device

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'ip link set br0 address $(cat /sys/class/net/wlan0/address)'

[Install]
WantedBy=multi-user.target

For more complex scenarios, consider using systemd-networkd-wait-online in your service:

# /etc/systemd/system/set-bridge-mac.service
[Unit]
Description=Set bridge MAC address
After=systemd-networkd-wait-online.service
Requires=systemd-networkd-wait-online.service

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'while ! ip link show br0 >/dev/null 2>&1; do sleep 1; done; ip link set br0 address $(cat /sys/class/net/wlan0/address)'

[Install]
WantedBy=multi-user.target

After implementing these changes:

  1. Enable the service: systemctl enable set-bridge-mac.service
  2. Restart networkd: systemctl restart systemd-networkd
  3. Verify with: ip link show br0 and check the MAC matches wlan0

Remember that the bridge must be fully initialized before modifying its MAC address, which is why we use device or networkd-wait dependencies.