Hi Ahmad, On Mon, Sep 11, 2023 at 05:59:27PM +0200, Ahmad Fatoum wrote: > From: Ahmad Fatoum <ahmad@xxxxxx> > > Especially during development, devices often lack a MAC address. While a > MAC address can be easily added to the environment: > > nv dev.eth0.ethaddr="aa:bb:cc:dd:ee:ff" > > It's easily lost when flashing complete new images, e.g. from CI. > Make the development experience neater by deriving a stable MAC address > if possible. > > Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> > --- > include/net.h | 2 ++ > net/Kconfig | 17 +++++++++++++++++ > net/eth.c | 11 ++++++++++- > net/net.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- > 4 files changed, 76 insertions(+), 3 deletions(-) > > diff --git a/include/net.h b/include/net.h > index a0ef8bee0404..de43c29f74ac 100644 > --- a/include/net.h > +++ b/include/net.h > @@ -418,6 +418,8 @@ static inline int is_broadcast_ether_addr(const u8 *addr) > #define ETH_ALEN 6 /* Octets in an Ethernet address */ > #define ETH_HLEN 14 /* Total octets in header.*/ > > +int generate_ether_addr(u8 *addr, int ethid); > + > /** > * random_ether_addr - Generate software assigned random Ethernet address > * @addr: Pointer to a six-byte array containing the Ethernet address > diff --git a/net/Kconfig b/net/Kconfig > index 59f14c23cba2..04fcdcbe5bd5 100644 > --- a/net/Kconfig > +++ b/net/Kconfig > @@ -6,6 +6,23 @@ menuconfig NET > > if NET > > +config NET_ETHADDR_FROM_MACHINE_ID > + bool > + prompt "generate stable Ethernet address" > + depends on MACHINE_ID && HAVE_DIGEST_SHA256 && HAVE_DIGEST_HMAC > + help > + By default, barebox will generate random Ethernet addresses for > + interfaces that had no explicit Ethernet address set via > + either board code or NVMEM properties in device tree. > + > + Say y here, to randomize Ethernet addresses only if no machine ID > + is available. Should barebox have a machine ID, it will be used > + alonside the hostname to generate MAC addresses that are unlikely s/alonside/alongside/ > + to change between subsequent runs of barebox. > + > + This is not recommended for use in production as it may leak > + information about the machine ID. > + > config NET_NFS > bool > prompt "nfs support" > diff --git a/net/eth.c b/net/eth.c > index ccac5e2a6488..e74c00e74a9a 100644 > --- a/net/eth.c > +++ b/net/eth.c > @@ -10,6 +10,7 @@ > #include <dhcp.h> > #include <net.h> > #include <dma.h> > +#include <machine_id.h> > #include <of.h> > #include <of_net.h> > #include <linux/phy.h> > @@ -558,6 +559,7 @@ static int of_populate_ethaddr(void) > { > char str[sizeof("xx:xx:xx:xx:xx:xx")]; > struct eth_device *edev; > + bool generated = false; > int ret; > > list_for_each_entry(edev, &netdev_list, list) { > @@ -566,11 +568,18 @@ static int of_populate_ethaddr(void) > > ret = of_get_mac_addr_nvmem(edev->parent->of_node, > edev->ethaddr); > + if (ret && IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID)) { > + ret = generate_ether_addr(edev->ethaddr, edev->dev.id); > + generated = true; > + } > if (ret) > continue; > > ethaddr_to_string(edev->ethaddr, str); > - dev_info(&edev->dev, "Got preset MAC address from device tree: %s\n", str); > + if (generated) > + dev_notice(&edev->dev, "Generated MAC address from unique id: %s\n", str); > + else > + dev_info(&edev->dev, "Got preset MAC address from NVMEM: %s\n", str); > eth_set_ethaddr(edev, edev->ethaddr); > } > > diff --git a/net/net.c b/net/net.c > index bf2117ff7ec2..e38179491d7a 100644 > --- a/net/net.c > +++ b/net/net.c > @@ -25,6 +25,7 @@ > #include <init.h> > #include <globalvar.h> > #include <magicvar.h> > +#include <machine_id.h> > #include <linux/ctype.h> > #include <linux/err.h> > > @@ -365,6 +366,43 @@ IPaddr_t net_get_gateway(void) > > static LIST_HEAD(connection_list); > > +/** > + * generate_ether_addr - Generates stable software assigned Ethernet address > + * @addr: Pointer to a six-byte array to contain the Ethernet address > + * @ethid: index of the Ethernet interface > + * > + * Derives an Ethernet address (MAC) from the machine ID, that's stable > + * per board that is not multicast and has the local assigned bit set. > + * > + * Return 0 if an address could be generated or a negative error code otherwise. > + */ > +int generate_ether_addr(u8 *ethaddr, int ethid) > +{ > + const char *hostname; > + uuid_t id; > + int ret; > + > + if (!IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID)) > + return -ENOSYS; > + > + hostname = barebox_get_hostname(); > + if (!hostname) > + return -EINVAL; > + > + ret = machine_id_get_app_specific(&id, ARRAY_AND_SIZE("barebox-macaddr:"), > + hostname, strlen(hostname), NULL); > + if (ret) > + return ret; > + > + memcpy(ethaddr, &id.b, ETH_ALEN); > + eth_addr_add(ethaddr, ethid); > + > + ethaddr[0] &= 0xfe; /* clear multicast bit */ > + ethaddr[0] |= 0x02; /* set local assignment bit (IEEE802) */ > + > + return 0; > +} > + > static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest, > rx_handler_f *handler, void *ctx) > { > @@ -381,9 +419,16 @@ static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest, > > if (!is_valid_ether_addr(edev->ethaddr)) { > char str[sizeof("xx:xx:xx:xx:xx:xx")]; > - random_ether_addr(edev->ethaddr); > + > + ret = generate_ether_addr(edev->ethaddr, edev->dev.id); > + if (ret) > + random_ether_addr(edev->ethaddr); > + > ethaddr_to_string(edev->ethaddr, str); > - dev_warn(&edev->dev, "No MAC address set. Using random address %s\n", str); > + > + dev_warn(&edev->dev, "No MAC address set. Using %s %s\n", > + ret == 1 ? "address computed from unique ID" : "random address", > + str); > eth_set_ethaddr(edev, edev->ethaddr); > } > > -- > 2.39.2 > > Regards Thorsten