use crate::models::*;
use crate::parser::ReadUtils;
use crate::ParserError;
use bytes::{Bytes, BytesMut};
use std::net::IpAddr;
pub fn parse_next_hop(mut input: Bytes, afi: &Option<Afi>) -> Result<AttributeValue, ParserError> {
if let Some(afi) = afi {
Ok(input.read_address(afi).map(AttributeValue::NextHop)?)
} else {
Ok(input
.read_address(&Afi::Ipv4)
.map(AttributeValue::NextHop)?)
}
}
pub fn parse_mp_next_hop(mut input: Bytes) -> Result<Option<NextHopAddress>, ParserError> {
let output = match input.len() {
0 => None,
4 => Some(input.read_ipv4_address().map(NextHopAddress::Ipv4)?),
16 => Some(input.read_ipv6_address().map(NextHopAddress::Ipv6)?),
32 => Some(NextHopAddress::Ipv6LinkLocal(
input.read_ipv6_address()?,
input.read_ipv6_address()?,
)),
v => {
return Err(ParserError::ParseError(format!(
"Invalid next hop length found: {}",
v
)));
}
};
Ok(output)
}
pub fn encode_next_hop(addr: &IpAddr) -> Bytes {
match addr {
IpAddr::V4(n) => Bytes::from(n.octets().to_vec()),
IpAddr::V6(n) => Bytes::from(n.octets().to_vec()),
}
}
#[allow(unused_variables, dead_code)]
pub fn encode_mp_next_hop(n: &NextHopAddress) -> Bytes {
match n {
NextHopAddress::Ipv4(n) => Bytes::from(n.octets().to_vec()),
NextHopAddress::Ipv6(n) => Bytes::from(n.octets().to_vec()),
NextHopAddress::Ipv6LinkLocal(n1, n2) => {
let mut output = BytesMut::with_capacity(32);
output.extend(n1.octets().to_vec());
output.extend(n2.octets().to_vec());
output.freeze()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::BytesMut;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;
#[test]
fn test_parse_next_hop() {
let ipv4 = Ipv4Addr::from_str("10.0.0.1").unwrap();
let ipv6 = Ipv6Addr::from_str("FC00::1").unwrap();
let ipv4_bytes = Bytes::from(ipv4.octets().to_vec());
let ipv6_bytes = Bytes::from(ipv6.octets().to_vec());
let res = parse_next_hop(ipv4_bytes, &None).unwrap();
if let AttributeValue::NextHop(n) = res {
assert_eq!(n.to_string(), "10.0.0.1".to_string())
}
let res = parse_next_hop(ipv6_bytes, &Some(Afi::Ipv6)).unwrap();
if let AttributeValue::NextHop(n) = res {
assert_eq!(n.to_string().to_ascii_uppercase(), "FC00::1".to_string())
}
}
#[test]
fn test_encode_next_hop() {
let ipv4 = Ipv4Addr::from_str("10.0.0.1").unwrap();
let ipv6 = Ipv6Addr::from_str("FC00::1").unwrap();
let ipv4_bytes = Bytes::from(ipv4.octets().to_vec());
let ipv6_bytes = Bytes::from(ipv6.octets().to_vec());
let _res = parse_next_hop(ipv4_bytes.clone(), &None).unwrap();
assert_eq!(ipv4_bytes, encode_next_hop(&ipv4.into()));
let _res = parse_next_hop(ipv6_bytes.clone(), &None).unwrap();
assert_eq!(ipv6_bytes, encode_next_hop(&ipv6.into()));
}
#[test]
fn test_parse_mp_next_hop() {
let ipv4 = Bytes::from(Ipv4Addr::from_str("10.0.0.1").unwrap().octets().to_vec());
let ipv6 = Bytes::from(Ipv6Addr::from_str("fc00::1").unwrap().octets().to_vec());
let ipv6_2 = Bytes::from(Ipv6Addr::from_str("fc00::2").unwrap().octets().to_vec());
if let Some(NextHopAddress::Ipv4(n)) = parse_mp_next_hop(ipv4).unwrap() {
assert_eq!(n.to_string(), "10.0.0.1".to_string())
}
if let Some(NextHopAddress::Ipv6(n)) = parse_mp_next_hop(ipv6.clone()).unwrap() {
assert_eq!(n.to_string(), "fc00::1".to_string())
}
let mut combined = BytesMut::from(ipv6.to_vec().as_slice());
combined.extend_from_slice(&ipv6_2);
if let Some(NextHopAddress::Ipv6LinkLocal(n, m)) =
parse_mp_next_hop(combined.into()).unwrap()
{
assert_eq!(n.to_string(), "fc00::1".to_string());
assert_eq!(m.to_string(), "fc00::2".to_string());
}
}
#[test]
fn test_encode_mp_next_hop() {
let ipv4 = Bytes::from(Ipv4Addr::from_str("10.0.0.1").unwrap().octets().to_vec());
let next_hop = parse_mp_next_hop(ipv4.clone()).unwrap().unwrap();
let bytes = encode_mp_next_hop(&next_hop);
assert_eq!(bytes, ipv4);
let ipv6 = Bytes::from(Ipv6Addr::from_str("fc00::1").unwrap().octets().to_vec());
let next_hop = parse_mp_next_hop(ipv6.clone()).unwrap().unwrap();
let bytes = encode_mp_next_hop(&next_hop);
assert_eq!(bytes, ipv6);
let ipv6_2 = Bytes::from(Ipv6Addr::from_str("fc00::2").unwrap().octets().to_vec());
let next_hop = parse_mp_next_hop(ipv6.clone()).unwrap().unwrap();
let bytes = encode_mp_next_hop(&next_hop);
assert_eq!(bytes, ipv6);
let mut combined = BytesMut::from(ipv6.to_vec().as_slice());
combined.extend_from_slice(&ipv6_2);
let next_hop = parse_mp_next_hop(combined.clone().into()).unwrap().unwrap();
let bytes = encode_mp_next_hop(&next_hop);
assert_eq!(bytes, combined);
let next_hop = parse_mp_next_hop(Bytes::new()).unwrap();
assert!(next_hop.is_none());
let next_hop = parse_mp_next_hop(Bytes::from(vec![1]));
assert!(next_hop.is_err());
}
}