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] -=-=-=-=-=-=-=-=-=-=-=-