This is a curious one and it may not be Mender related, but here goes anyways. I’m on Raspberry Pi 3B’s / 3B+'s and what I’m observing is that upon booting a fresh image from Yocto on the Pi it seems to be somehow locking the mac address of that Pi’s Ethernet adapter into the SD card. If I move that SD card to another Raspberry Pi, it will boot up and be using the mac address from the first Pi. I’m seeing this both in Linux and U-Boot, though I can’t find any files that are changing in the boot partition.
Has anyone seen anything like this before?
Edit: After further investigation, it looks like the address gets locked in after first booting into Linux, and a number of u-boot variables appear in printenv after that first Linux boot, including a mender variable. So I’m pretty sure it’s something Mender. Looking through the doc now. (I’m still on 1.7)
By default the RPi will query the boot firmware for the MAC address and this is how it gets a “unique” address for each device.
Interestingly though as you already might have figured out, the code that you link to will prioritize the ethaddr environment variable over what the response is from boot firmware.
Meaning that if you run e.g:
# setenv ethaddr 00:11:22:33:44:55
# saveenv
This address will be used and this is stored on the SD card, meaning that it will follow when you move the SD card to another device.
This might also happen in mender_setup where do call saveenv meaning that if ethaddr is set to something when mender_setup is run it will save it to the SD card.
Yeah, I’m not sure what the best general solution will be. For my purposes I can just change that line so it always sets the Mac address from the usbethaddr variable, but I believe the ethaddr flag is meant to be modified by the user.
Also, to be clear, the actual issue is that Linux is using the mac address from ethaddr. So hopefully changing that line in u-boot would fix it in Linux as well, but I’m not aware of the mechanism by which Linux gets the address. I can find the hard-coded (not actual device) MAC address within the /proc/device-tree but I’m not 100% sure that that’s where the ethernet driver gets the MAC from.
@mirzak So the problem mostly stems from the original u-boot source that I linked above but the saveenv seems to be the thing that causes the damage. I’m also seeing that a card that I boot in a RPi 3B fails to boot in a 3B+ and I suspect that some other environment variable that’s being saved is responsible for it. Is there an alternative to saveenv? Can we just save specific variables to permanent storage?
Right now I’m working on a patch for u-boot for the Mac address thing, but I’m worried about what other side effects happen due to doing the saveenv. Right now we’re working on finding and removing all Raspberry Pi 3B’s from the office so we don’t have the cross-over failure.
First of all thanks for digging in to this and reporting back your findings. The findings are relevant and actually also explains some things that I have experienced as well but never understood (why moving SD card from RPi3 Model B to B+ did not work)
I am not aware of any alternatives to saveenv and you always write the whole environment in one go, this is also something that makes changes to the environment atomic and this is important to keep intact.
Right now I’m working on a patch for u-boot for the Mac address thing, but I’m worried about what other side effects happen due to doing the saveenv. Right now we’re working on finding and removing all Raspberry Pi 3B’s from the office so we don’t have the cross-over failure.
The purpose of the saveenv command is to detect inconsistencies in environment configuration between U-boot and the user-space. This is what mender_saveenv_canary=1 is used for and this is the purpose of the saveenv. The Mender client will actually check the presence of this variable and complain if it is not there. That is at least my understanding as I have not looked in to these specific parts in a while.
Note that the saveenv is only executed once, during the first boot.
Trying to run env default -a before calling saveenv will force it to re-write the U-boot environment on each boot, this is not desirable as it will cause “wear” on the SD card and increase chances of breaking blocks. Something to avoid to increase longevity of your device.
With all that said, I do not really see any major side-effects/downsides of this behaviour expect that you might not be able to move an SD card that has booted once from a RPi3 B+ to RPi 3 B. But I would argue that every time you move the SD card to between devices there are other reasons on why you would re-provision it again to get a fresh start, even if it is from RPi3 B+ to RPi3 B+.
One reason is the device identity which is used by Mender and this is typically a hardware bound identifier. Now in this specific case it is using the defaults (MAC address, which was carried over due to the U-boot environment) but this is something that is configurable and might as well have been something else that is not related to the U-boot environment.
And would not be to worried about the saveenv causing other problems as this is the environment that your device boots with and the result of the saveenv will only save it to disk, but it would otherwise contain these variables even if we did not do the saveenv.
Glad that I helped, and thanks for the detailed response!
I think I mostly agree. This is a problem that’s only occurring for us because we’re in a rapid build-test-deploy cycle where we’re testing on one board before moving the SD card to another board. Some of the other research I’ve done since my last post implies that u-boot was never intended to be moved from one board to another, especially with respect to the ethaddr variable.