use core::net::Ipv6Addr;
pub fn create_link_local_ipv6(mac: &[u8; 6]) -> Ipv6Addr {
Ipv6Addr::new(
0xfe80,
0,
0,
0,
u16::from_be_bytes([mac[0] ^ 0x02, mac[1]]),
u16::from_be_bytes([mac[2], 0xff]),
u16::from_be_bytes([0xfe, mac[3]]),
u16::from_be_bytes([mac[4], mac[5]]),
)
}
pub fn compute_group_multicast_addr(fabric_id: u64, group_id: u16) -> Ipv6Addr {
let prefix = 0xfd00_0000_0000_0000_u64 | ((fabric_id >> 8) & 0x00ff_ffff_ffff_ffff);
let group32 = ((fabric_id as u32) << 24) | group_id as u32;
let mut octets = [0u8; 16];
octets[0] = 0xff;
octets[1] = 0x35; octets[2] = 0x00; octets[3] = 0x40; octets[4..12].copy_from_slice(&prefix.to_be_bytes());
octets[12..16].copy_from_slice(&group32.to_be_bytes());
Ipv6Addr::from(octets)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::alloc::string::ToString;
extern crate alloc;
#[test]
fn test_compute_group_multicast_addr() {
let addr = compute_group_multicast_addr(0x0001_0002_0003_0004, 0x0001);
let octets = addr.octets();
assert_eq!(octets[0], 0xff);
assert_eq!(octets[1], 0x35);
assert_eq!(octets[2], 0x00);
assert_eq!(octets[3], 0x40);
assert_eq!(&octets[4..12], &0xfd00_0100_0200_0300_u64.to_be_bytes());
assert_eq!(&octets[12..16], &0x04000001_u32.to_be_bytes());
}
#[test]
fn test_create_link_local_ipv6() {
let mac = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc];
let ipv6 = create_link_local_ipv6(&mac);
assert_eq!(ipv6.to_string(), "fe80::1034:56ff:fe78:9abc");
let mac2 = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55];
let ipv6_2 = create_link_local_ipv6(&mac2);
assert_eq!(ipv6_2.to_string(), "fe80::211:22ff:fe33:4455");
let mac3 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
let ipv6_3 = create_link_local_ipv6(&mac3);
assert_eq!(ipv6_3.to_string(), "fe80::302:3ff:fe04:506");
}
}