What is the systemd-networkd equivalent of post-up? (dynamic bridge MAC configuration)
Solution 1:
It turns out that due to the heavy modular concept of systemd
and systemd-networkd
the scripting question needs to be tackled from a different angle: instead of looking for scripting with the bridge .netdev
definition, the systemd
way is to have a (very small) one-shot .service
unit that is wanted by the bridge .netdev
.
As a side note: it seems that in more recent Linux kernels, the kernel bridges actually don't use the dynamically changing lowest MAC48 scheme for the bridge MAC48 anymore. Instead, they create a static MAC48 for the bridge itself. So, in the very strict sense this solution is not really needed anymore, unless one prefers to use a "real" hardware MAC48; which is what is done here in the following service unit.
The necessary new service unit (in lieu of the old post-up
from /etc/network/interfaces
) lives in /etc/systemd/system/bridge-stable-mac.service
and assigns the MAC48 from (built-in, fixed) wlan0
to the bridge itself:
[Service]
Type=oneshot
ExecStart=/bin/bash -c "/bin/echo 'br0 available, setting MAC ' `/bin/cat /sys/class/net/wlan0/address`"
ExecStart=/bin/bash -c "/sbin/ip link set br0 address `/bin/cat /sys/class/net/wlan0/address`"
[Install]
WantedBy=sys-subsystem-net-devices-br0.device
The central point here is the WantedBy=
clause: whenever br0
starts, then this service should be run (exactly once, Type=oneshot
). Systemd is really neat here, as it doesn't need to edit the existing device definition in order to add our dependency, but instead calculates this dependency using our inverse WantedBy=
link. This is really where I think that systemd
does shine.
The service unit above assumes that your bridge is named br0
. You should use a corresponding .netdev
file to define this bridge br0
. For instance, in /etc/systemd/network/10-br0.netdev
:
[NetDev]
Name=br0
Kind=bridge
When it comes to hotplugging bridge ports, systemd
actually does this already out-of-the-box, which is very neat; in /etc/systemd/network/10-br0-ports.network
:
[Match]
Name=eth0 wlan0
[Network]
Bridge=br0
That's it!