How does Linux determine the default MAC address of a bridge device? I know it is the same as "bridge id" from brctl show, but how is it calculated? Is the MAC address supposed to change automatically when a network interface is added to the bridge?
1 Answers
Behavior might possibly have changed in the past depending on kernel version, but currently (here: kernel 5.17.x) it appears that:
if the bridge has not be manually given a MAC address then
- it initially gets an autogenerated random MAC address with private bit set (ie: 2nd digit in MAC address' first byte is always 2,6,a or e).
- until the first time an interface is set as bridge port, when administratively UP it gets a LOWER_UP flag and its operstate is UNKNOWN, which gives it the benefit of the doubt as if UP (eg with
systl -w net.ipv4.conf.br0.ignore_routes_with_linkdown=1, route is working and doesn't have thelinkdownproperty). - once at least one interface has ever been enslaved as bridge port:
- each time a bridge port is added or removed the bridge interface dynamically inherits the lowest MAC address among all its bridge ports' MAC addresses.
- should it then lose all of its interfaces, its MAC address becomes 00:00:00:00:00:00, until a port is added back
- its operstate is UP if it's administratively UP and at least one of its bridge ports has operstate UP (usually: administratively UP and has carrier, ie: doesn't have the NO-CARRIER property)
- if administratively UP but all of its ports have operstate DOWN (usually: administratively DOWN or have the NO-CARRIER property) then the bridge interface gets the NO-CARRIER property and its operstate is DOWN (and for example with
ignore_routes_with_linkdown=1, routes will have thedead/linkdownproperties).
if the bridge's MAC address is set manually (with a different value than from its current auto-generated or inherited address if not set at creation)
the bridge's MAC address will not change when bridge ports are added or removed
operstate isn't UNKNOWN when administratively set UP when there has never been any bridge port added yet: it's DOWN.
and follows the previously described behavior with regard to its operstate and its port's operstates : UP when there's at least a bridge port with operstate UP, DOWN otherwise.
I couldn't find any documentation explaining the reason for these different behaviors related to having or not having set a MAC address on the bridge on Linux. There might possibly be an historical relation to how the bridge id is evaluated.
To avoid any surprise, just set the MAC address.
Example for a bridge named br0:
ip link set dev br0 address 12:34:56:78:9a:bc
or at creation:
ip link add name br0 address 12:34:56:78:9a:bc up type bridge
One can still set it with the MAC address of some pre-existing (physical) interface intended to be enslaved, for example to avoid changing DHCP behavior when requesting an IP address on br0 without using DUID. It should probably be set before enslaving the interface because setting it after might actually have no effect as written above (setting the bridge interface's MAC address to its same current value has no effect and doesn't switch to the second behavior).
For example to copy eth0's MAC address when creating br0 to keep DHCP behavior consistent (with eth0 intended to be enslaved to br0 and on the side of the DHCP server), with the help of JSON output and the jq command:
ip link add name br0 address "$(ip -json link show dev eth0 | jq -r .[].address)" up type bridge
and only then enslave the interface:
ip link set dev eth0 up master br0
One can only hope existing network configuration tools can do this correctly.
Note: just as ifconfig or route on Linux, brctl is an obsolete command. It still uses the older kernel API. This has been superseded by ip link plus bridge which use the newer (rt)netlink API providing new features (eg: hairpin), but arguably may have a less human-readable output.
Example of commands:
ip -details link show type bridge
bridge -details link show
- 6,306