diff --git a/site/ipam.md b/site/ipam.md index 74288e93..a50893c1 100644 --- a/site/ipam.md +++ b/site/ipam.md @@ -176,20 +176,26 @@ for manual allocation. ## Stopping and removing peers -You may wish to `weave stop` and re-launch to change some config or to -upgrade to a new version; provided the underlying protocol hasn't -changed it will pick up where it left off and learn from peers in the -network which address ranges it was previously using. If, however, you -run `weave reset` this will remove the peer from the network so -if Weave is run again on that node it will start from scratch. +You may wish to `weave stop` and re-launch to change a peer's +configuration or upgrade it to a new version. Provided the underlying +protocol hasn't changed the peer will pick up where it left off and +learn from other peers in the network which address ranges it was +previously using. -For failed peers, the `weave rmpeer` command can be used to -permanently remove the ranges allocated to said peer. This will allow -other peers to allocate IPs in the ranges previously owner by the rm'd -peer, and as such should be used with extreme caution - if the rm'd -peer had transferred some range of IP addresses to another peer but -this is not known to the whole network, or if it later rejoins -the Weave network, the same IP address may be allocated twice. +The same normally happens when a peer is restarted any other way, +e.g. as result of a reboot, provided the +[system-uuid](http://linux.die.net/man/8/dmidecode) didn't change. + +If you want to remove a peer from the network, run `weave reset`. This +removes the ranges allocated to the peer, thus allowing other peers to +allocate IPs in them. + +For a failed peer, the `weave rmpeer` command can be run on any other +peer to achieve the same result. The command should be used with +extreme caution - if the rm'd peer had transferred some range of IP +addresses to another peer but this is not known to the whole network, +or if it actually had not failed and later rejoins the network, the +same IP address may be allocated twice. Assuming we had started the three peers in the example earlier, and host3 has caught fire, we can go to one of the other hosts and run: diff --git a/weave b/weave index 2de5a231..23ac3fc0 100755 --- a/weave +++ b/weave @@ -432,12 +432,18 @@ arp_update() { ! command_exists arping || $3 arping -U -q -I $1 -c 1 ${2%/*} } -# Generate a random MAC value -random_mac() { +# Generate a MAC value from a stdin containing six space separated +# 2-digit hexadecimal numbers. +mac_from_hex() { # In the first byte of the MAC, the 'multicast' bit should be # clear and 'locally administered' bit should be set. All other # bits should be random. - od -txC -An -N6 /dev/urandom | ( read a b c d e f && printf "%02x:$b:$c:$d:$e:$f" $((0x$a & ~1 | 2)) ) + read a b c d e f && printf "%02x:$b:$c:$d:$e:$f" $((0x$a & ~1 | 2)) +} + +# Generate a random MAC value +random_mac() { + od -txC -An -N6 /dev/urandom | mac_from_hex } ###################################################################### @@ -585,10 +591,22 @@ init_bridge() { ip link add name $BRIDGE type bridge - # Set a random MAC address on the bridge. Current Linux - # kernels already do this when creating a bridge, but there - # are rumours it was not always so. - ip link set dev $BRIDGE address $(random_mac) + # Derive the bridge MAC from the system (aka bios) UUID, if + # present. Elsewhere we in turn derive the peer name from that, + # which we want to be stable across reboots but otherwise + # unique. The system UUID fits that bill, unlike, say, + # /etc/machine-id, which is often identical on VMs created from + # cloned filesystems. If we cannot determine the system UUID we + # just generate a random MAC. + if SYSTEM_UUID=$(cat /sys/class/dmi/id/product_uuid 2>/dev/null) ; then + # We salt the input just as a precaution to avoid clashes with + # other applications who might have had the bright idea of + # generating MACs in the same way. + MAC=$(echo "9oBJ0Jmip-$SYSTEM_UUID" | sha256sum | sed 's/\(..\)/\1 /g' | cut -c1-17 | mac_from_hex) + else + MAC=$(random_mac) + fi + ip link set dev $BRIDGE address $MAC # Attempting to set the bridge MTU to a high value directly # fails. Bridges take the lowest MTU of their interfaces. So @@ -1514,12 +1532,9 @@ launch_router() { enforce_docker_bridge_addr_assign_type create_bridge docker_bridge_ip - # We set the router name to the bridge mac since that is - # stable across re-creations of the containers. - # - # TODO use the mac of one of the physical host interfaces - # (eth0, wlan0, etc) so the name becomes stable across host - # restarts. + # We set the router name to the bridge MAC, which in turn is + # derived from the system UUID (if available), and thus stable + # across reboots. PEERNAME=$(cat /sys/class/net/$BRIDGE/address) # backward compatibility... if is_cidr "$1" ; then