mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Sascha Hauer <sha@pengutronix.de>
To: Ahmad Fatoum <a.fatoum@pengutronix.de>
Cc: barebox@lists.infradead.org,
	Alexander Shiyan <eagle.alexander923@gmail.com>
Subject: Re: [PATCH 3/3] net: add generic MAC address derivation from machine ID
Date: Tue, 12 Sep 2023 12:49:03 +0200	[thread overview]
Message-ID: <20230912104903.GA637806@pengutronix.de> (raw)
In-Reply-To: <20230911155927.3786335-3-a.fatoum@pengutronix.de>

On Mon, Sep 11, 2023 at 05:59:27PM +0200, Ahmad Fatoum wrote:
> From: Ahmad Fatoum <ahmad@a3f.at>
> 
> 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.

I like this, because my Fritzbox network overview is full of duplicate
entries coming from boards with random MAC addresses.


> @@ -558,6 +559,7 @@ static int of_populate_ethaddr(void)

This function should be renamed. When reviewing this patch I asked
myself why you limit generating a fixed MAC address to the DT case until
I realized that you actually don't. I was just confused by the function
name.

>  {
>  	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)) {

This check doesn't seem to be needed, generate_ether_addr() already
returns -ENOSYS when this option is not enabled.

> +			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);

For most network devices we won't get here because of_populate_ethaddr()
will already have done it for us. It's only used for devices that are
probed after postenvironment_initcall(), namely USB devices.

I think this deserves a cleanup before we merge this. The original
reason to introduce a postenvironment_initcall() for getting the MAC
address from nvmem was:

> We do this in a very late initcall, because we don't want to enforce a
> probe a probe order between nvmem providers and network devices. We
> can't do it at randomization time, because we need to fixup Ethernet mac
> addresses, even when barebox itself doesn't ifup the netdev.

I think we should have one centralized function that retrieves the MAC
address for an ethernet device. That should be called when we actually
need that MAC address, so once in net_new() and once at of_fixup time.

Right now the behaviour is inconsistent with regard to random MAC
addresses. Currently we propagate the random MAC address to the Linux
device tree when we use ethernet in barebox, but we don't propagate it
when we do not use ethernet in barebox. We should decide what the
desired behaviour is and do it consistently regardless if we use
ethernet in barebox or not. This could be cleaned up along the way.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



  reply	other threads:[~2023-09-12 10:50 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-11 15:59 [PATCH 1/3] common: machine_id: support deriving app specific UUIDs Ahmad Fatoum
2023-09-11 15:59 ` [PATCH 2/3] net: import Linux eth_addr_inc/dec/add helpers Ahmad Fatoum
2023-09-11 15:59 ` [PATCH 3/3] net: add generic MAC address derivation from machine ID Ahmad Fatoum
2023-09-12 10:49   ` Sascha Hauer [this message]
2023-09-12 12:34     ` Ahmad Fatoum
2023-10-05  6:56       ` Ahmad Fatoum
2023-10-06 11:59       ` Sascha Hauer
2023-10-12 14:59         ` Alexander Shiyan
2023-10-13 11:11           ` Sascha Hauer
2023-10-17  9:39             ` Ahmad Fatoum
2023-09-15 15:23   ` Thorsten Scherer
2023-09-21 11:12 ` [PATCH 1/3] common: machine_id: support deriving app specific UUIDs Sascha Hauer
2023-09-22  9:45 ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230912104903.GA637806@pengutronix.de \
    --to=sha@pengutronix.de \
    --cc=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=eagle.alexander923@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox