sys/luid: add luid_get_eui48() / luid_get_eui64()#12592
sys/luid: add luid_get_eui48() / luid_get_eui64()#12592benpicco merged 4 commits intoRIOT-OS:masterfrom
Conversation
Hmm, I don't think this is the right way to do this. The data There was some discussion about having a generic network device configuration module using the |
It still does generate locally unique IDs. The first one will be equal to the EUI64MAC (or CPU ID if the former does not exist), the others will be derived from it. If you don't care about the content and just want a unique but constant ID, just keep calling If you want the value verbatim, you can still use |
If one would want to access a compile time constant byte array in verbatim, one could just declare it as a global byte array and access it directly. I see no reason to have a fancy API in that use case. Being able to override |
|
Back to the issue with callers of Maybe a better solution would be to an additional function like this: typedef enum {
LUID_LEADING_ZEROS_AT_LSB, /**< the least significat byte will be filled with leading zeros */
LUID_LEADING_ZEROS_AT_MSB, /**< the most significat byte will be filled with leading zeros */
LUID_ALIGN_NUMOF, /**< Number of alignment options */
} luid_align_t;
/**
* @brief Generate a locally unique number with the given number of bits
* @param buf The generated ID is stored here
* @param n_bits The bit-length of the ID to generate
* @param alignment Should leading zeros be added to the first or last byte of the ID
*
* If @p n_bits is a multiple of 8, this will be equivalent to a call of `luid_get(buf, n_bits/8);`
*/
luid_get_bits(void *buf, size_t n_bits, luid_align_t alignment);In the given case one could use this like this: uint8_t euid64[8];
luid_get_bits(euid64, 62, LUID_LEADING_ZEROS_AT_LSB);
euid64[0] <<= 2; |
|
Hm, I didn't want to change the luid API with this PR, but rather fix the existing implementation while keeping the API. The API already says
Which IMHO should be enough for most applications. |
There is nothing nothing to fix in LUID. When I have e.g. four Also: People might actually rely on the value The problem the driver (incorrectly) tries to solve is to get a 62 bit locally unique ID. This is currently not possible with the API. Changing the algorithm to mitigate (rather than fix!) the issue does not really solve the general issue: It would still be impossible to generate e.g. 7 bit IDs. |
maribu
left a comment
There was a problem hiding this comment.
NACK. Doesn't solve the general issue and breaks LUID for users relying on LUID to keep generate the same IDs for their hardware.
|
(If you would drop the change of the algorithm and only keep |
|
I don't think there is a nice way to fix this and not change the generated MAC addresses in some way. |
|
For the |
When I look at e.g. addr->uint8[0] |= EUI48_LOCAL_FLAG;
addr->uint8[0] &= ~EUI48_GROUP_FLAG; |
|
I think this is the more saner approach compared to changing all device drivers (and potentially doing something wrong because byte-order issues tend to put knots in peoples brains). I always found it weird that the entropy of |
I think that this is a good design in context of the use case described by the API: Generating IDs that are
I also believe this to be true most of the time. With those two things in mind let's say a huge company is installing smart light bulbs. They would very likely buy a huge number of identical light bulbs in a single transaction. Those will likely contain MCUs produces by the same manufacturer on the same day. So if the MCU manufacturer has the id
So if indeed that head of the CPU IDs is often identical, the trailer is the part containing most of the "uniqueness", and the first byte is the one containing the "least amount of uniqueness". If we only modify the first byte for subsequent calls of Because of this, I think that only changing the first byte is a good design choice. Also: I like the fact that LUIDs (with at least a few bytes in length) generated on the same node can often easily be linked to that node. E.g. if devices would have multiple 802.15.4 transceivers, I could (often) easily see which long addresses belong to the same device. |
How about adding |
|
Brain is slow... luid_get_ can in theory clash with any vendor registered OUI? The EUI48_LOCAL_FLAG to save us? The bit even vaild for EUI64. No private or usable OUI's? |
|
I'm following this discussion. |
miri64
left a comment
There was a problem hiding this comment.
The more I think about it I come to the conclusion that this should be a different module, as it is basically completely changing the implementation. As for luid "classic": I think for the use-case of using its result as MAC address it suffices that the LSB instead of the MSB is changing on re-calls. I will open a PR for that.
|
(this is a NACK in case this stays |
@miri64: Keep in mind that the LSB of the CPU ID is the one containing the most "uniqueness". The best way to go for me would be to simply append the counter to the CPU ID, rather than modifying byte of the CPU ID. That way it is guaranteed for LUIDs (with length >= CPU-ID-length + 1) to never collide, if the CPU IDs didn't collide. |
|
On Mon, Nov 04, 2019 at 03:58:20AM -0800, Koen Zandberg wrote:
> Instead of this `mac_idx` counter, maybe something along the lines of the driver name (used already in the thread name) and the position in the `xxx_params_t` array is sufficient.
Still a bit of a hack though :)
Hmm, having a driver-specific info would be good if one interface
has a paid-for unique mac address. In that case the driver info
helps to distinguish for which interfaces a board-specific callback
wants to set the MAC if there is more than one interface.
See #12616 for my use-case.
So maybe a hack for the use-case of assigning a random mac but
very useful for a fixed unique mac.
Ralf
--
Dr. Ralf Schlatterbeck Tel: +43/2243/26465-16
Open Source Consulting www: http://www.runtux.com
Reichergasse 131, A-3411 Weidling email: office@runtux.com
|
I agree that code wanting to assign specific L2 addresses to specific network devices have tremendous interest in knowing which device they are just assigning an address. However, this info should not be exposed to LUID in my opinion, as LUID is only about providing locally unique IDs. So to me, it should not be concerned with any details of the network stack (or other users of LUIDs) (*). This information is easily available in the network modules, so to my opinion the L2 address assignment should be done there (with calls to (*) with the exception of the format of the LUID. Having callers of LUID meddle with the generated IDs risks creating collisions even on the same boards (for less than 256 IDs), without carefully checking the implementation of LUID. |
|
On Mon, Nov 04, 2019 at 05:54:05AM -0800, Marian Buschsieweke wrote:
I agree that code wanting to assign specific L2 addresses to specific
network devices have tremendous interest in knowing which device they
are just assigning an address. However, this info should not be
exposed to LUID in my opinion, [...]
Of course not, but factoring out the MAC-Adress generation of all boards
into a non board-specific method that is called by all hardware drivers
would ease integration of different methods for MAC-Adress generation
later on (or allow override in a board-specific package).
Maybe this can be done with this patch, too.
Ralf
--
Dr. Ralf Schlatterbeck Tel: +43/2243/26465-16
Open Source Consulting www: http://www.runtux.com
Reichergasse 131, A-3411 Weidling email: office@runtux.com
|
|
OK, now since the consensus seems to be that there should be a two-layer approach, this PR now only deals with adding |
maribu
left a comment
There was a problem hiding this comment.
ACK. Thanks for addressing this!
|
Ran all unit tests (including the one on LUID provided by this PR) on a Nucleo-F767ZI: |
|
@benpicco: I think you can feel free to squash. |
This allows to overwrite luid_base() with a function that reads an ID from e.g. a EUI64MAC chip if no CPU ID is available.
The most common use case for luid is to generate those addresses, so provide helper functions for it.
You could have saved yourself some time and only run |
The F767ZI executes the additional tests faster than I can type |
My comments and concerns were addressed. Let's go ahead with this.
|
(Let's run the tests, just to be sure). |
Contribution description
The
luid_get()function is used to generate a hardware address for networking interfaces.For this, the lowest to bits of the first byte are always set to a defined value.
This is problematic as the current
luid_get()implementation will only increment the first byte, resulting in a different address on every third invocation only:To fix this and not duplicate the EUI48/64 generation logic in every driver, add dedicated functions for that use-case.
@herjulf wanted to source the MAC address from an EUI64MAC chip if no CPU id is present.
With this PR this is possible by implementing a custom
size_t luid_get_eui64_custom(eui64_t *addr, uint8_t idx)function.This also adds a unit test to ensure that two calls to
luid_get_eui64_custom()have different results and two calls toluid_custom()have the same result if the same generator is used.Testing procedure
Run
make -C tests/unittests tests-luid.Also make sure that unique hardware addresses for network interfaces are still generated.Drivers are not yet converted to the new API.
Issues/PRs references
came up in #12537