Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] MacAddress shold be able to map to EUI-64 bytes for legacy support #45

Open
rheone opened this issue Nov 9, 2019 · 1 comment
Labels
enhancement New feature or request requires discussion a discussion is required before any perminent action is taken

Comments

@rheone
Copy link
Member

rheone commented Nov 9, 2019

Description

A legacy use of a MAC Address is to convert it to a EUI-64.

This will allow us to also support the legacy modification of a EUI-64 as the least-significant 64 bits of a unicast network address or link-local address when stateless address autoconfiguration is used.

Eg. MAC Address to IPv6

Proposed solutions

There are several sources that say several things about this mapping; it is unclear which is "most" correct, or what the variants imply.

It seems odd that each of the 3 below mentioned very specifically outlining differing rules for what would seem to be the same operation. While IEEE is the definitive source, I'd like to determine the reasoning of the other implementations before moving forward. The differing schemes may be perfectly valid in the appropriate place.

All this for a known legacy operation 🤷

Networking Engineering StackExchange

(current implementation)
Answer to "What are EUI-48 and EUI-64?"
states that the insertion bytes should be [0xFF, 0xFE] and 7th bit should be inverted.

Wikipedia entry for "Mac Address"

Mac Address. Citation Note 6
states that the insertion bytes should be [0xFF, 0xFE] if the source is a EUI-48
and that the insertion bytes should be [0xFF, 0xFF] if the source is a MAC-48
(no inversion of any bits mentioned)

IEE

IEEE in "Guidelines for Use of Extended Unique Identifier (EUI), Organizationally Unique Identifier (OUI), and Company ID (CID)" section "Mapping an EUI-48 to an EUI-64" (pg 15)
states that the insertion bytes should be [0xFF, 0xFE] or [0xFF, 0xFF]
(no inversion of any bits mentioned)

Can you help?

Maybe? Gotta clear some things up and do some research

Code

What follows is the "StackExchange" implementation. This exists simply because it is what I first encountered before researching further. By no means is it the "correct" solution, it is simply correct as to the implied spec.

/// <summary>Gets a mapping of the Mac Address as a EUI-64</summary>
/// <remarks><para>Note that this mapping is considered deprecated, and is implemented for legacy needs</para></remarks>
/// <remarks><para>The implementation of this method is under question</para></remarks>
/// <returns>an array of bytes representing the EUI-64 of the MAC Address</returns>
[NotNull]
[Obsolete("This method is obsolete until the desired output can be verified")]
public byte[] GetEui64AddressBytes()
{
   // To generate a EUI-64 from the EUI-48
   // - divided EUI-48 int two 3-byte parts; OUI & CID
   // - insert the value 0xFFFE between the two parts (24th bit)
   // - Invert the 7th bit of the result

   var eui64 = new byte[8];
   Array.Copy(this._address, 0, eui64, 0, 3);  // first 3 bytes od address
   eui64[3] = 0xFF;
   eui64[4] = 0xFE;
   Array.Copy(this._address, 3, eui64, 5, 3);  // last 3 bytes of address

   // invert the 7th bit
   if ((eui64[0] & 0b0000_0010) != 0)  // 7th bit (big-endian) is set, it should be cleared
   {
         eui64[0] &= 0b1111_1101;    // clear the 7th bit
   }
   else  // 7th bit (big-endian) is not set, it should be set
   {
         eui64[0] |= 0b0000_0010;    // set the 7th bit
   }

   return eui64;
}

Tests

public static IEnumerable<object[]> GetEui64AddressBytes_Test_Values()
{
   yield return new object[] { new byte[] { 0x02, 0x21, 0x86, 0xFF, 0xFE, 0xB5, 0x6E, 0x10 }, MacAddress.Parse("00:21:86:B5:6E:10") };
   yield return new object[] { new byte[] { 0xFD, 0x21, 0x86, 0xFF, 0xFE, 0xB5, 0x6E, 0x10 }, MacAddress.Parse("FF:21:86:B5:6E:10") };
   yield return new object[] { new byte[] { 0xC2, 0xFF, 0xEE, 0xFF, 0xFE, 0xCA, 0xFE, 0x00 }, MacAddress.Parse("C0:FF:EE:CA:FE:00") };
}

[Theory]
[MemberData(nameof(GetEui64AddressBytes_Test_Values))]
public void GetEui64AddressBytes_Test(byte[] expected, MacAddress input)
{
   // Arrange
   // Act
   var result = input.GetEui64AddressBytes();

   // Assert
   Assert.IsType<byte[]>(result);
   var addressBytes = input.GetAddressBytes();

   Assert.Equal(8, result.Length);
   Assert.NotEqual(expected[0] & 0b10, addressBytes[0] & 0b10);
   Assert.Equal(0xFF, result[3]);
   Assert.Equal(0xFE, result[4]);
   Assert.Equal(0, ByteArrayUtils.CompareUnsignedBigEndian(expected, result));
}
@rheone rheone added enhancement New feature or request requires discussion a discussion is required before any perminent action is taken labels Nov 9, 2019
rheone added a commit that referenced this issue Nov 9, 2019
#45
There is confusion related to this issue
@rheone
Copy link
Member Author

rheone commented Feb 3, 2020

Comment from user goulashsoup

"... I was also curious about the bit inversion. Actually most tutorials and descriptions are wrong about it. The bit inversion is used to get the "Modified EUI-64" as described in RFC 4291 to acquire the interface identifier. Therefor the correct "EUI-64" value does not include the inversion. See also Understanding IPv6 EUI-64 Bit Address"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request requires discussion a discussion is required before any perminent action is taken
Projects
None yet
Development

No branches or pull requests

1 participant