1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2021 Vladimir Melnikov.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module describes NLRI data structures for vpls

use crate::*;
use crate::afi::*;

/// BGP VPLS NLRI
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct BgpAddrL2 {
    pub rd: BgpRD,
    pub site: u16,
    pub offset: u16,
    pub range: u16,
    pub labels: MplsLabels,
}
impl BgpItemLong<BgpAddrL2> for BgpAddrL2 {
    fn extract_from(size: usize, buf: &[u8]) -> Result<BgpAddrL2, BgpError> {
        if size < 17 {
            return Err(BgpError::from_string(format!(
                "Invalid FEC length for BgpAddrL2: {:?} bytes",
                size
            )));
        }
        let srd = BgpRD::decode_from(BgpTransportMode::IPv4, buf)?;
        let lbls = MplsLabels::extract_bits_from(((size - 14) * 8) as u8, &buf[14..])?;
        Ok(BgpAddrL2 {
            rd: srd.0,
            site: getn_u16(&buf[8..10]),
            offset: getn_u16(&buf[10..12]),
            range: getn_u16(&buf[12..14]),
            labels: lbls.0,
        })
    }
    fn pack_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
        if buf.len()<15 {
            return Err(BgpError::insufficient_buffer_size());
        }
        self.rd.encode_rd_to(buf)?;
        setn_u16(self.site,&mut buf[8..10]);
        setn_u16(self.offset,&mut buf[10..12]);
        setn_u16(self.range,&mut buf[12..14]);
        let r=self.labels.set_bits_to(&mut buf[14..])?;
        Ok(r.1+14)
    }
}
impl std::fmt::Display for BgpAddrL2 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "<{}> {}::{}..{}",
            self.rd, self.site, self.offset, self.range
        )
    }
}
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct BgpL2 {
    pub rd: BgpRD,
    pub site: u16,
    pub offset: u16,
    pub range: u16,
}
impl BgpL2 {
    pub fn new(srd: BgpRD, st: u16, ofs: u16, rng: u16) -> BgpL2 {
        BgpL2 {
            rd: srd,
            site: st,
            offset: ofs,
            range: rng,
        }
    }
}
impl std::fmt::Display for BgpL2 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "<{}>site {}-{}..{}",
            self.rd, self.site, self.offset, self.range
        )
    }
}
impl BgpAddrItem<BgpL2> for BgpL2 {
    fn decode_from(mode: BgpTransportMode, buf: &[u8]) -> Result<(BgpL2, usize), BgpError> {
        if buf.len() >= 14 {
            let rdp = BgpRD::decode_from(mode, &buf[0..8])?;
            Ok((
                BgpL2 {
                    rd: rdp.0,
                    site: getn_u16(&buf[8..10]),
                    offset: getn_u16(&buf[10..12]),
                    range: getn_u16(&buf[12..14]),
                },
                14,
            ))
        } else {
            Err(BgpError::static_str("Invalid BgpL2 buffer len"))
        }
    }
    fn encode_to(&self, mode: BgpTransportMode, buf: &mut [u8]) -> Result<usize, BgpError> {
        let pos = self.rd.encode_to(mode, buf)?;
        setn_u16(self.site, &mut buf[pos..]);
        setn_u16(self.offset, &mut buf[pos + 2..]);
        setn_u16(self.range, &mut buf[pos + 4..]);
        Ok(pos + 6)
    }
}

#[cfg(feature = "serialization")]
impl serde::Serialize for BgpAddrL2 {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut state = serializer.serialize_struct("BgpAddrL2", 5)?;
        state.serialize_field("rd", &self.rd)?;
        state.serialize_field("site", &self.site)?;
        state.serialize_field("offset", &self.offset)?;
        state.serialize_field("range", &self.range)?;
        state.serialize_field("labels", &self.labels)?;
        state.end()
    }
}