1

I read somewhere (in a few places, actually, can't seem to find the references to it now that I want them) that Raspbian on the Raspberry Pi generates the MAC address for the Ethernet interface based on the serial number of the Pi, combined with the Raspberry Pi foundation OUI.

I'm working on a product which uses the Compute Module as the core, and has the same SMSC Ethernet module the Pi 3 has - and so it ends up getting a MAC address in a similar way to the Pi 3. My company has its own OUI which we can use, so I'd like to have our devices use our OUI instead of the RPi Foundation's one.

I've tried looking through the source code of the RPi Linux kernel branch, but can't seem to find the part where this is generated. Can someone point me in the right direction?

Basically, I'd like to keep the same auto-generation of the MAC (so that we don't have to add an EEPROM to store the MAC), but use a custom OUI instead of the RPi Foundation one.

seanlano
  • 131
  • 1
  • 8
  • 1
    So, all you want to do is override the MAC address for the ethernet interface? along the lines of https://raspberrypi.stackexchange.com/a/88936/33057 – Jaromanda X Nov 12 '18 at 12:54
  • Somewhat like that, but I guess I want to do it on a wildcard kind of basis - I only want to replace the first 3 octets. The intention is to do this in an automated fashion, without needing to configure a unique configuration file for each device. – seanlano Nov 12 '18 at 21:46

3 Answers3

3

Here's something I came up with that probably does what you want

What this does is get the serial number of the pi (32 bit number from /proc/cpuinfo or OTP location 28) - the last 24 bits of which are the last half of the ethernet MAC address (no idea how pi3 wifi MAC address is "calculated")

Then, by creating a systemd.link file, you can override the default MAC address

Having the following script run at boot (perhaps in /etc/rc.local) the file /etc/systemd/network/00-default.link will be created if it does not exist.

You will need a reboot to take effect - perhaps that could be part of the script

#!/bin/sh
magic="/etc/systemd/network/00-default.link"
RPIoui="b8:27:eb"
MYoui="fe:18:00"
if [ ! -f $magic ]; then
    mac=$(awk '/Serial/ {print $3}' /proc/cpuinfo | sed 's/^.*\(..\)\(..\)\(..\)$/\1:\2:\3/')
    # or you can get the same info from OTP
    # mac=$(vcgencmd otp_dump | grep "^28:" | sed -e 's/^.*\(..\)\(..\)\(..\)$/\1:\2:\3/')
    cat > $magic <<EOF
[Match]
MACAddress=$RPIoui:$mac

[Link]
MACAddress=$MYoui:$mac
EOF
    # reboot here?
fi

The above will create a file /etc/systemd/network/00-default.link that will look like

[Match]
MACAddress=b8:27:eb:12:34:56

[Link]
MACAddress=fe:18:00:12:34:56
Jaromanda X
  • 2,415
  • 1
  • 13
  • 14
  • Thanks, I'll give this a go. Looking at the documentation for systemd.link, it seems like I might even be able to "match" on some combination of the path and maybe driver, which would let it be even more generic and not need to match on the existing MAC address. – seanlano Nov 12 '18 at 22:45
  • Sure. But why not match the mac you want to change. – Jaromanda X Nov 12 '18 at 22:46
  • Ah yep, sorry, had a few thoughts and didn't write them all down - I saw that there's this "customer OTP" section of memory, and now I'm thinking I might program our custom MAC into that and then use something like what you've posted here as the basis for reading and setting it as the MAC in use. If I do that, then I no longer really care what the original MAC was. – seanlano Nov 12 '18 at 22:50
  • there's this "customer OTP" section of memory - intrigued, where is this documented? Personally, I wouldn't start messing with OTP :p – Jaromanda X Nov 12 '18 at 22:57
  • I came across this after you mentioned the serial in OTP location 28: https://www.raspberrypi.org/documentation/hardware/industrial/README.md – seanlano Nov 12 '18 at 22:59
  • 1
    Yeah, I just found that - interesting - not something the average Pi "hacker" (like me) would need, but I can see how in your situation it could be useful - there's so much more to the Pi than meets the eye! – Jaromanda X Nov 12 '18 at 23:03
  • I thought I'd have a go setting the address with a shell command, like so: MACAddress=$( echo "00:00:00:cc:ec:e5" ) - but it didn't work. :( – seanlano Nov 13 '18 at 00:18
  • Huh. That's nothing like adding a systemd.link file so I'm not surprised – Jaromanda X Nov 13 '18 at 00:20
  • Oh, I see what you mean ... just put MACAddress=00:00:00:cc:ec:e5 - don't use commands like echo etc in a "here document" – Jaromanda X Nov 13 '18 at 00:29
1

The last 6 bytes of MAC and CPUID are identical BUT are NOT generated by Raspbian. The code is probably buried in firmware (if not in the custom code).

CPUID=$(awk '/Serial/ {print $3}' /proc/cpuinfo | sed 's/^0*//')
MAC=$(cat /sys/class/net/eth0/address)
echo $CPUID
f72402e7
echo $MAC
b8:27:eb:24:02:e7
Milliways
  • 59,890
  • 31
  • 101
  • 209
  • "The code is probably buried in firmware (if not in the custom code)" - I guess this is the core of my question really, where is this code? – seanlano Nov 12 '18 at 21:47
  • 1
    well, the last 32 bits of the serial number are held in OTP location 28 (and inversed in OTP 29) - perhaps that will help you find the code – Jaromanda X Nov 12 '18 at 21:50
  • Thanks for the pointer on the OTP bits - this led me to this page: https://www.raspberrypi.org/documentation/hardware/raspberrypi/otpbits.md which says "64/65 – MAC address; if set, system will use this in preference to the automatically generated address based on the serial number". This then led me to https://www.raspberrypi.org/documentation/hardware/industrial/README.md which seems to describe how to program the OTP bits - I will investigate! :) – seanlano Nov 12 '18 at 22:11
  • Oh, although then there's this comment: "Also, from 36 to 43 (inclusive), there are eight rows of 32 bits available for the customer". Bummer, can't program 64 and 65. I might just try it anyway, see what happens. – seanlano Nov 12 '18 at 22:13
0

Building on the answer from Jaromanda X, this is the configuration I've ended up going with.


I really wanted to find some way to generate the systemd.link file automatically on boot, and have it applied at boot without needing it to be saved to disk and the system rebooted - but I just couldn't find a way to do this. So I've done it in two parts, a bash script and a systemd job to run it.

First, a script, which I've saved as /usr/local/bin/ethernet-mac.sh:

#!/bin/bash

temp_path=$( mktemp )
conf_path="/etc/systemd/network/00-ethernet.link" 

mac=$(vcgencmd otp_dump | grep "^28:" | sed -e 's/^.*\(..\)\(..\)\(..\)$/\1:\2:\3/')
oui="00:0a:bc" 

cat > ${temp_path} <<EOF
[Match]
Driver=smsc95xx

[Link]
MACAddress=${oui}:${mac}
EOF

if ! cmp ${temp_path} ${conf_path} -s
then
    rm -f ${conf_path}
    cp ${temp_path} ${conf_path}
    sync
    reboot
fi

Then the systemd config at /etc/systemd/system/ethernet-mac.service:

[Unit]
Description=Ethernet MAC address assignment
Before=networking.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/ethernet-mac.sh

[Install]
WantedBy=network.target

Enable the service with sudo systemctl enable ethernet-mac.service.

Now, on each boot, the job will call the script, which will check that the systemd.link file is as it should be - if it is not, then it updates the file and reboots the system.

The file generated at /etc/systemd/network/00-ethernet.link looks like this:

[Match]
Driver=smsc95xx

[Link]
MACAddress=00:0a:bc:cc:ec:e5
seanlano
  • 131
  • 1
  • 8