How to build an OpenStack alternative: Step 3, Generating Mac Addresses

Posted on 2020-01-13 by ungleich virtualisation team

This time we describe how to begin automation in uncloud, our OpenStack alternative.

The previous time we described how to secure the network.

Mac Addresses

Mac addresses are identifiers for network cards. Like a street number is for a house. A virtual machine can have one or more network interfaces. Each of these interfaces need a unique number, the mac address.

Choosing the prefix

We checked how OpenNebula is doing it. They basically use the 02:00 prefix and generate mac addresses after that. The QEMU mac address prefix seems to be 52:54:00. According to Michael Stapelberg the f6 prefix can be used due to the second lowest bit set to 1.

Checking with Wikipedia, this bit indeed specifies whether or not a mac address is locally or universally administrated.

For that reason we will use 42 as our prefix, which is 1000010 in binary and thus has the second least significant bit set to 1.

Generating Mac addresses

Mac addresses are basically just numbers and so we treat them as such. We need to store the index of which is the current mac address and for the next time we create a VM, use the next mac address.

The python code to generate a new mac address looks as follows:

    @staticmethod
    def int_to_mac(number):
        b = number.to_bytes(6, byteorder="big")
        return ':'.join(format(s, '02x') for s in b)

    def getnext(self):
        if self.last:
            last_number = int(self.last[0], 16)

            if last_number == int('0xffffff', 16):
                raise Error("Exhausted all possible mac addresses - try to free some")

            next_number = last_number + 1
        else:
            next_number = 0

        next_number_string = "{:012x}".format(next_number)

        next_mac_number = self.prefix + next_number
        next_mac = self.int_to_mac(next_mac_number)

It basically says:

  • If there has been a mac address used add 1 to it and use the next one
  • Produce an error, if the whole prefix has been used
  • If no mac address has been used, use the first one
  • Convert the number to the standard format (aa:bb:cc:dd:ee:ff)

There is some additional logic on saving the MAC address to which we will come back in one of the next posts.

Using the MAC address generator

From our prototype, we modify the original vm.sh script to include a call to the mac address generator as follows:

...
mac=$(./mac-gen.py)
...
$qemu -name "uncloud-${uuid}" \
      -machine pc,accel=${accel} \
      -m ${memory} \
      -smp ${cores} \
      -uuid ${uuid} \
      -drive file=alpine-virt-3.11.2-x86_64.iso,media=cdrom \
      -netdev tap,id=netmain,script=./ifup.sh,downscript=./ifdown.sh \
      -device virtio-net-pci,netdev=netmain,id=net0,mac=${mac}

In good UNIX manner, the generator simply outputs the MAC address on stdout to be used by any software.

Status

While being a small and very specific tool, the mac address generator is actually a key element of creating a virtualisation framework. Without it, it is practically impossible to spawn a dynamic amount of virtual machines.

With our prototype, a secured network and the mac address generator we are not far from being able to migrate some test VMs to uncloud.