Folks,

I have stumbled across two functions that purport to construct a
link-local IPv6 address from a MAC address.  A laudable goal,
but the details need some review.

One function can be found in src/vnet/ip/ip6.h:

always_inline void
ip6_link_local_address_from_ethernet_mac_address (ip6_address_t * ip,
                                                  u8 * mac)
{
  ip->as_u64[0] = clib_host_to_net_u64 (0xFE80000000000000ULL);
  /* Invert the "u" bit */
  ip->as_u8[8] = mac[0] ^ (1 << 1);
  ip->as_u8[9] = mac[1];
  ip->as_u8[10] = mac[2];
  ip->as_u8[11] = 0xFF;
  ip->as_u8[12] = 0xFE;
  ip->as_u8[13] = mac[3];
  ip->as_u8[14] = mac[4];
  ip->as_u8[15] = mac[5];
}

I draw your attention to the assignment to ip->as_u8[8], where bit 0x02 is
XOR'ed in.

The second function is found in src/vnet/ip/ip6_packet.h:

always_inline void
ip6_link_local_address_from_ethernet_address (ip6_address_t * a,
                                              const u8 * ethernet_address)
{
  a->as_u64[0] = a->as_u64[1] = 0;
  a->as_u16[0] = clib_host_to_net_u16 (0xfe80);
  /* Always set locally administered bit (6). */
  a->as_u8[0x8] = ethernet_address[0] | (1 << 6);
  a->as_u8[0x9] = ethernet_address[1];
  a->as_u8[0xa] = ethernet_address[2];
  a->as_u8[0xb] = 0xff;
  a->as_u8[0xc] = 0xfe;
  a->as_u8[0xd] = ethernet_address[3];
  a->as_u8[0xe] = ethernet_address[4];
  a->as_u8[0xf] = ethernet_address[5];
}

Here, I draw your attention to the similar assignment to a->as_u8[8] where
bit 0x40 is OR'ed in.

I will grant you that confusion exists in the literature.  Let's dispense
with
"counting from 0" and "counting from 1", and guessing if the displayed bits
are ordered Left to Right as 0 to 7, or 7 to 0.   Let's talk powers of 2
instead.

My understanding, though possibly wrong, is that 2^1 of byte 8 is the
question.
So I believe the (1 << 6) is wrong.  So we'll talk about 0x02, which I
believe is correct.

Now, should the bit be set, or XOR'ed?  There are arguments for both cases,
so I
do not know which is correct and desired here.  Specifically, given a MAC
address,
does that 0x02 bit need to be inverted to maintain its Global/Local status
as it is
copied to the IPv6 address?  Do we even want to maintain its G/L status?
Or do
we want to force it to be locally administered by slamming the bit to 1?

I am happy to submit a patch to fix this situation, but I'd like to make
sure we get it right. :-)

Here's what I think we should do:
    - Remove the function ip6_link_local_address_from_ethernet_address() as
it
      contains the incorrect bit, (1 << 6).
    - Replace the one use of that function with a call to
      ip6_link_local_address_from_ethernet_mac_address() instead.
    - Answer the bit-wise XOR vs OR question ...?

Other suggestions or advice?

Thanks,
jdl
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#13280): https://lists.fd.io/g/vpp-dev/message/13280
Mute This Topic: https://lists.fd.io/mt/32054012/21656
Group Owner: vpp-dev+ow...@lists.fd.io
Unsubscribe: https://lists.fd.io/g/vpp-dev/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to