What is the systemd-networkd equivalent of post-up? (dynamic bridge MAC configuration)
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!
Related videos on Youtube
Comments
-
TheDiveO over 1 year
In Linux distributions that use
/etc/network/interfaces
(such as Debian) I could get a (kernel) bridge to use the MAC48 address of one of its static bridge slave interfaces, such as a built inwlan0
, usingpost-up
, as in:post-up ip link set br0 address `cat /sys/class/net/wlan0/address`
This ensured that both 1) each cloned system used its very own unique MAC48 (the one from the unique wlan0), and 2) the bridge MAC kept stable even when hot-plugging further bridge interfaces with lower MAC48's.
Does systemd-networkd support any kind of
post-up
commands that can be run after a network (or netdev) has been brought up? I've tried to find such a thing, but may have missed it.Or is the correct way in systemd completely different, i.e. to have a device unit, and a service that wraps the
ip link...
command and depends on the device unit? If so, how would the device unit and the service unit files look like? -
iBug over 2 yearsI wonder if
RemainAfterExit=yes
is needed for the service.