use crate::afi::*;
#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg(feature = "serialization")]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
pub struct MacAddress {
pub mac_address: [u8; 6],
}
impl MacAddress {
pub fn new() -> MacAddress {
MacAddress {
mac_address: [0_u8; 6],
}
}
pub fn from_network_bytes(b: &[u8]) -> MacAddress {
MacAddress {
mac_address: [b[5], b[4], b[3], b[2], b[1], b[0]],
}
}
pub fn write_to_network_bytes(&self, b: &mut [u8]) {
let [b0, b1, b2, b3, b4, b5] = self.mac_address;
b.copy_from_slice(&[b5, b4, b3, b2, b1, b0]);
}
pub fn from_u64(s: u64) -> MacAddress {
let mut a = [0_u8; 6];
a[0] = (s & 0xff) as u8;
a[1] = ((s >> 8) & 0xff) as u8;
a[2] = ((s >> 16) & 0xff) as u8;
a[3] = ((s >> 24) & 0xff) as u8;
a[4] = ((s >> 32) & 0xff) as u8;
a[5] = ((s >> 40) & 0xff) as u8;
MacAddress { mac_address: a }
}
pub fn to_u64(&self) -> u64 {
(self.mac_address[5] as u64) << 40
| (self.mac_address[4] as u64) << 32
| (self.mac_address[3] as u64) << 24
| (self.mac_address[2] as u64) << 16
| (self.mac_address[1] as u64) << 8
| (self.mac_address[0] as u64)
}
}
impl Default for MacAddress {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for MacAddress {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
self.mac_address[5],
self.mac_address[4],
self.mac_address[3],
self.mac_address[2],
self.mac_address[1],
self.mac_address[0],
)
}
}
impl std::fmt::Debug for MacAddress {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
self.mac_address[5],
self.mac_address[4],
self.mac_address[3],
self.mac_address[2],
self.mac_address[1],
self.mac_address[0]
))
}
}
impl std::str::FromStr for MacAddress {
type Err = BgpError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut mac: u64 = 0;
let mut cnt: usize = 0;
for c in s.chars() {
if let Some(d) = c.to_digit(16) {
mac = (mac << 4) | (d as u64);
cnt += 1;
}
}
if cnt < 1 {
return Err(BgpError::static_str("Invalid mac address"));
}
Ok(MacAddress::from_u64(mac))
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct BgpAddrMac {
pub addr: MacAddress,
pub prefixlen: u8,
}
impl BgpAddrMac {
pub fn new(address: MacAddress, prefix_len: u8) -> BgpAddrMac {
BgpAddrMac {
addr: address,
prefixlen: prefix_len,
}
}
fn norm_subnet_u48(&self) -> u64 {
self.addr.to_u64() & (((1 << (48 - self.prefixlen)) - 1) ^ 0xffffffffffff)
}
pub fn in_subnet(&self, a: &MacAddress) -> bool {
if self.prefixlen == 0 {
true
} else if self.prefixlen > 47 {
self.addr.to_u64() == a.to_u64()
} else {
let lv = self.norm_subnet_u48();
let lh = lv + ((1 << (48 - self.prefixlen)) - 1);
let va = a.to_u64();
(va >= lv) && (va <= lh)
}
}
pub fn range_first(&self) -> MacAddress {
MacAddress::from_u64(self.norm_subnet_u48())
}
pub fn range_last(&self) -> MacAddress {
if self.prefixlen < 1 {
MacAddress::from_u64(0xffffffffffff)
} else if self.prefixlen > 47 {
self.range_first()
} else {
let lv = self.norm_subnet_u48() + ((1 << (48 - self.prefixlen)) - 1);
MacAddress::from_u64(lv)
}
}
pub fn contains(&self, a: &BgpAddrMac) -> bool {
if self.prefixlen < 1 {
true
} else if self.prefixlen > a.prefixlen {
false
} else if self.prefixlen == a.prefixlen {
self.addr == a.addr
} else {
self.in_subnet(&a.range_first()) && self.in_subnet(&a.range_last())
}
}
}
impl std::str::FromStr for BgpAddrMac {
type Err = BgpError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = s.split('/').collect();
if parts.len() < 2 {
Ok(BgpAddrMac {
addr: parts[0].parse::<MacAddress>()?,
prefixlen: 48,
})
} else {
Ok(BgpAddrMac {
addr: parts[0].parse::<MacAddress>()?,
prefixlen: parts[1].parse::<u8>().unwrap_or(48),
})
}
}
}
impl std::fmt::Display for BgpAddrMac {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}/{}", self.addr, self.prefixlen)
}
}