use inetnum::addr::Prefix;
use octseq::OctetsFrom;
use std::cmp;
use std::fmt;
use octseq::{Octets, OctetsBuilder, Parser};
use crate::util::parser::ParseError;
use super::common::{compose_prefix_without_len, parse_prefix_for_len, prefix_bits_to_bytes};
use super::afisafi::Afi;
#[derive(Copy, Clone, Debug, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MplsNlri<Octs> {
prefix: Prefix,
labels: Labels<Octs>,
}
impl<O> MplsNlri<O> {
pub fn new(prefix: Prefix, labels: Labels<O>) -> Self {
Self { prefix, labels }
}
pub fn prefix(&self) -> Prefix {
self.prefix
}
pub fn labels(&self) -> &Labels<O> {
&self.labels
}
}
impl<Octs: Octets> MplsNlri<Octs> {
pub fn parse<'a, R>( parser: &mut Parser<'a, R>,
afi: Afi,
) -> Result<Self, ParseError>
where
R: Octets<Range<'a> = Octs>
{
let (prefix, labels) = parse_labels_prefix(parser, afi)?;
Ok(
MplsNlri::new(prefix,labels,)
)
}
}
fn parse_labels_prefix<'a, R, Octs>(
parser: &mut Parser<'a, R>,
afi: Afi,
) -> Result<(Prefix, Labels<Octs>), ParseError>
where
Octs: Octets,
R: Octets<Range<'a> = Octs>
{
let mut prefix_bits = parser.parse_u8()?;
let labels = Labels::<Octs>::parse(parser)?;
if u8::try_from(8 * labels.len())
.map_err(|_| ParseError::form_error("MplsNlri labels too long"))?
> prefix_bits {
return Err(ParseError::ShortInput);
}
prefix_bits -= 8 * labels.len() as u8;
let prefix = parse_prefix_for_len(
parser,
prefix_bits,
afi,
)?;
Ok((prefix, labels))
}
impl<Octs: AsRef<[u8]>> MplsNlri<Octs> {
pub(super) fn compose_len(&self) -> usize {
self.labels.len() + prefix_bits_to_bytes(self.prefix.len())
}
pub(super) fn compose<Target: OctetsBuilder>(&self, target: &mut Target)
-> Result<(), Target::AppendError>
{
let len = u8::try_from(8 * self.labels.len()) .unwrap_or(u8::MAX) +
self.prefix.len();
target.append_slice(&[len])?;
target.append_slice(self.labels.as_ref())?;
compose_prefix_without_len(self.prefix, target)
}
}
impl<Octs: AsRef<[u8]>> Eq for MplsNlri<Octs> { }
impl<Octs, Other> PartialEq<MplsNlri<Other>> for MplsNlri<Octs>
where Octs: AsRef<[u8]>,
Other: AsRef<[u8]>
{
fn eq(&self, other: &MplsNlri<Other>) -> bool {
self.prefix == other.prefix && self.labels == other.labels
}
}
impl<Octs> PartialOrd for MplsNlri<Octs>
where Octs: AsRef<[u8]>,
{
fn partial_cmp(&self, other: &MplsNlri<Octs>) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<Octs: AsRef<[u8]>> Ord for MplsNlri<Octs> {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.prefix.cmp(&other.prefix).then(self.labels.as_ref().cmp(other.labels.as_ref()))
}
}
impl<T> fmt::Display for MplsNlri<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "MPLS:{}", self.prefix())
}
}
impl<Octs, SrcOcts: Octets> OctetsFrom<MplsNlri<SrcOcts>> for MplsNlri<Octs>
where Octs: OctetsFrom<SrcOcts>,
{
type Error = Octs::Error;
fn try_octets_from(
source: MplsNlri<SrcOcts>
) -> Result<Self, Self::Error> {
Ok(MplsNlri {
prefix: source.prefix,
labels: Labels::try_octets_from(source.labels)?
})
}
}
#[derive(Copy, Clone, Debug, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Labels<Octs> {
octets: Octs
}
impl<Octs: AsRef<[u8]>> Labels<Octs> {
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.octets.as_ref().len()
}
}
#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct Label {
data: u32
}
impl Label {
pub fn value(self) -> u32 {
self.data >> 12
}
pub fn experimental(self) -> u8 {
((self.data >> 9) as u8) & 0x07
}
pub fn bottom(self) -> bool {
self.data & 0x100 == 0x100
}
pub fn ttl(self) -> u8 {
self.data as u8
}
}
impl fmt::Display for Label {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.value())?;
if self.bottom() {
write!(f, " (bottom)")?
}
Ok(())
}
}
impl<Octs: Octets> Labels<Octs> {
pub fn parse<'a, R>(parser: &mut Parser<'a, R>) -> Result<Self, ParseError>
where
R: Octets<Range<'a> = Octs> + ?Sized,
{
let pos = parser.pos();
let mut stop = false;
let mut buf = [0u8; 3];
while !stop {
parser.parse_buf(&mut buf)?;
if buf[2] & 0x01 == 0x01 || buf == [0x80, 0x00, 0x00] || buf == [0x00, 0x00, 0x00] {
stop = true;
}
}
let len = parser.pos() - pos;
parser.seek(pos)?;
let res = parser.parse_octets(len)?;
Ok(
Labels { octets: res }
)
}
}
impl<Octs: AsRef<[u8]>> Labels<Octs> {
pub fn iter(&self) -> LabelsIterator<'_, Octs> {
LabelsIterator { parser: Parser::from_ref(&self.octets) }
}
}
pub struct LabelsIterator<'a, Octs> {
parser: Parser<'a, Octs>
}
impl<O: AsRef<[u8]>> Iterator for LabelsIterator<'_, O> {
type Item = Label;
fn next(&mut self) -> Option<Self::Item> {
if self.parser.remaining() == 0 {
return None;
}
let mut buf = [0u8; 4];
self.parser.parse_buf(&mut buf[0..3]).expect("must be multiple of 3 bytes left");
Some(Label { data: u32::from_be_bytes(buf) } )
}
}
impl<O: AsRef<[u8]>> fmt::Display for Labels<O> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut iter = self.iter();
if let Some(first) = iter.next() {
write!(f, "{}", first)?;
}
for l in iter {
write!(f, ", {}", l)?;
}
Ok(())
}
}
impl<Octs: AsRef<[u8]>> Eq for Labels<Octs> { }
impl<Octs, Other> PartialEq<Labels<Other>> for Labels<Octs>
where Octs: AsRef<[u8]>,
Other: AsRef<[u8]>
{
fn eq(&self, other: &Labels<Other>) -> bool {
self.octets.as_ref() == other.octets.as_ref()
}
}
impl<Octs: AsRef<[u8]>> AsRef<[u8]> for Labels<Octs> {
fn as_ref(&self) -> &[u8] {
self.octets.as_ref()
}
}
impl<Octs, SrcOcts: Octets> OctetsFrom<Labels<SrcOcts>> for Labels<Octs>
where Octs: OctetsFrom<SrcOcts>,
{
type Error = Octs::Error;
fn try_octets_from(
source: Labels<SrcOcts>
) -> Result<Self, Self::Error> {
Ok(Labels {
octets: Octs::try_octets_from(source.octets)?
})
}
}
#[cfg(test)]
mod tests {
use octseq::Parser;
use super::*;
use std::str::FromStr;
#[test]
fn parse() {
let raw = vec![
0x38, 0x01, 0xf4, 0x01, 0x0a, 0x00, 0x00, 0x09,
0x32, 0x01, 0xf4, 0x11, 0xc6, 0x33, 0x64, 0x00,
0x32, 0x01, 0xf4, 0x21, 0xc6, 0x33, 0x64, 0x40,
0x32, 0x01, 0xf4, 0x31, 0xc6, 0x33, 0x64, 0x80,
0x32, 0x01, 0xf4, 0x91, 0xc6, 0x33, 0x64, 0xc0
];
let mut parser = Parser::from_ref(&raw);
let mut res = vec![];
while parser.remaining() > 0 {
res.push(MplsNlri::parse(&mut parser, Afi::Ipv4).unwrap());
}
assert_eq!(res.len(), 5);
assert_eq!(res[0].prefix(), Prefix::from_str("10.0.0.9/32").unwrap());
}
#[test]
fn label() {
let label = Label { data: 0x00012aff};
assert_eq!(label.value(), 18);
assert_eq!(label.experimental(), 0b101);
assert!(!label.bottom());
assert_eq!(label.ttl(), 255);
assert_eq!(label.to_string(), "18");
let label = Label { data: 0x00010bff};
assert_eq!(label.value(), 16);
assert_eq!(label.experimental(), 0b101);
assert!(label.bottom());
assert_eq!(label.ttl(), 255);
assert_eq!(label.to_string(), "16 (bottom)");
}
#[test]
fn labels() {
let raw = vec![
0x50,
0x01, 0x3a, 0x70,
0x01, 0x3a, 0x81,
0x0a, 0x00, 0x00, 0x09,
];
let mut parser = Parser::from_ref(&raw);
let mut res = vec![];
while parser.remaining() > 0 {
res.push(MplsNlri::parse(&mut parser, Afi::Ipv4).unwrap());
}
assert_eq!(res.len(), 1);
let labels = res[0].labels();
assert_eq!(labels.iter().count(), 2);
assert_eq!(
format!("{}", labels),
"5031, 5032 (bottom)"
);
}
}