Skip to content

Commit

Permalink
isis: implement the LSPBufferSize TLV
Browse files Browse the repository at this point in the history
This TLV is primarily used for troubleshooting purposes. A warning
should be emitted when receiving this TLV with a value different
from the locally configured ("lsp-mtu"), which will be addressed in
a separate commit along with other changes.

Signed-off-by: Renato Westphal <[email protected]>
  • Loading branch information
rwestphal committed Jan 3, 2025
1 parent 0d88e2f commit 4a01363
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 14 deletions.
3 changes: 2 additions & 1 deletion holo-isis/src/lsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ fn lsp_build_tlvs(
LspTlvs::new(
protocols_supported,
instance.config.area_addrs.clone(),
Some(instance.config.lsp_mtu),
is_reach,
ext_is_reach,
ipv4_addrs,
Expand Down Expand Up @@ -360,7 +361,7 @@ fn lsp_build_tlvs_pseudo(
}
}

LspTlvs::new([], [], is_reach, ext_is_reach, [], [], [], [], [], [])
LspTlvs::new([], [], None, is_reach, ext_is_reach, [], [], [], [], [], [])
}

fn lsp_build_fragments(
Expand Down
1 change: 1 addition & 0 deletions holo-isis/src/northbound/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ fn load_callbacks() -> Callbacks<Instance> {
ipv6_te_routerid: None,
protocol_supported: Some(Box::new(protocol_supported)),
dynamic_hostname: None,
lsp_buffer_size: lsp.tlvs.lsp_buf_size(),
})
})
.path(isis::database::levels::lsp::attributes::PATH)
Expand Down
1 change: 1 addition & 0 deletions holo-isis/src/packet/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub enum TlvType {
Neighbors = 6,
Padding = 8,
LspEntries = 9,
LspBufferSize = 14,
ExtIsReach = 22,
Ipv4InternalReach = 128,
ProtocolsSupported = 129,
Expand Down
24 changes: 22 additions & 2 deletions holo-isis/src/packet/pdu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::packet::tlv::{
tlv_entries_split, tlv_take_max, AreaAddressesTlv, ExtIpv4Reach,
ExtIpv4ReachTlv, ExtIsReach, ExtIsReachTlv, Ipv4AddressesTlv, Ipv4Reach,
Ipv4ReachTlv, Ipv6AddressesTlv, Ipv6Reach, Ipv6ReachTlv, IsReach,
IsReachTlv, LspEntriesTlv, LspEntry, NeighborsTlv, PaddingTlv,
ProtocolsSupportedTlv, Tlv, UnknownTlv, TLV_HDR_SIZE,
IsReachTlv, LspBufferSizeTlv, LspEntriesTlv, LspEntry, NeighborsTlv,
PaddingTlv, ProtocolsSupportedTlv, Tlv, UnknownTlv, TLV_HDR_SIZE,
};
use crate::packet::{AreaAddr, LanId, LevelNumber, LevelType, LspId, SystemId};

Expand Down Expand Up @@ -102,6 +102,7 @@ pub struct Lsp {
pub struct LspTlvs {
pub protocols_supported: Option<ProtocolsSupportedTlv>,
pub area_addrs: Vec<AreaAddressesTlv>,
pub lsp_buf_size: Option<LspBufferSizeTlv>,
pub is_reach: Vec<IsReachTlv>,
pub ext_is_reach: Vec<ExtIsReachTlv>,
pub ipv4_addrs: Vec<Ipv4AddressesTlv>,
Expand Down Expand Up @@ -600,6 +601,10 @@ impl Lsp {
let tlv = AreaAddressesTlv::decode(tlv_len, &mut buf_tlv)?;
tlvs.area_addrs.push(tlv);
}
Some(TlvType::LspBufferSize) => {
let tlv = LspBufferSizeTlv::decode(tlv_len, &mut buf_tlv)?;
tlvs.lsp_buf_size = Some(tlv);
}
Some(TlvType::IsReach) => {
let tlv = IsReachTlv::decode(tlv_len, &mut buf_tlv)?;
tlvs.is_reach.push(tlv);
Expand Down Expand Up @@ -683,6 +688,9 @@ impl Lsp {
for tlv in &self.tlvs.area_addrs {
tlv.encode(&mut buf);
}
if let Some(tlv) = &self.tlvs.lsp_buf_size {
tlv.encode(&mut buf);
}
for tlv in &self.tlvs.is_reach {
tlv.encode(&mut buf);
}
Expand Down Expand Up @@ -807,6 +815,7 @@ impl LspTlvs {
pub(crate) fn new(
protocols_supported: impl IntoIterator<Item = u8>,
area_addrs: impl IntoIterator<Item = AreaAddr>,
lsp_buf_size: Option<u16>,
is_reach: impl IntoIterator<Item = IsReach>,
ext_is_reach: impl IntoIterator<Item = ExtIsReach>,
ipv4_addrs: impl IntoIterator<Item = Ipv4Addr>,
Expand All @@ -821,6 +830,7 @@ impl LspTlvs {
protocols_supported,
)),
area_addrs: tlv_entries_split(area_addrs),
lsp_buf_size: lsp_buf_size.map(|size| LspBufferSizeTlv { size }),
is_reach: tlv_entries_split(is_reach),
ext_is_reach: tlv_entries_split(ext_is_reach),
ipv4_addrs: tlv_entries_split(ipv4_addrs),
Expand All @@ -840,6 +850,10 @@ impl LspTlvs {
rem_len -= protocols_supported.len();
}
let area_addrs = tlv_take_max(&mut self.area_addrs, &mut rem_len);
let lsp_buf_size = self.lsp_buf_size.take();
if let Some(lsp_buf_size) = &lsp_buf_size {
rem_len -= lsp_buf_size.len();
}
let is_reach = tlv_take_max(&mut self.is_reach, &mut rem_len);
let ext_is_reach = tlv_take_max(&mut self.ext_is_reach, &mut rem_len);
let ipv4_addrs = tlv_take_max(&mut self.ipv4_addrs, &mut rem_len);
Expand All @@ -858,6 +872,7 @@ impl LspTlvs {
Some(LspTlvs {
protocols_supported,
area_addrs,
lsp_buf_size,
is_reach,
ext_is_reach,
ipv4_addrs,
Expand All @@ -884,6 +899,11 @@ impl LspTlvs {
self.area_addrs.iter().flat_map(|tlv| tlv.list.iter())
}

// Returns the maximum sized LSP which may be generated (TLV type 14).
pub(crate) fn lsp_buf_size(&self) -> Option<u16> {
self.lsp_buf_size.as_ref().map(|tlv| tlv.size)
}

// Returns an iterator over all IS neighbors from TLVs of type 2.
pub(crate) fn is_reach(&self) -> impl Iterator<Item = &IsReach> {
self.is_reach.iter().flat_map(|tlv| tlv.list.iter())
Expand Down
35 changes: 35 additions & 0 deletions holo-isis/src/packet/tlv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ pub struct PaddingTlv {
pub length: u8,
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct LspBufferSizeTlv {
pub size: u16,
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct ProtocolsSupportedTlv {
Expand Down Expand Up @@ -359,6 +365,35 @@ impl PaddingTlv {
}
}

// ===== impl LspBufferSizeTlv =====

impl LspBufferSizeTlv {
const SIZE: usize = 2;

pub(crate) fn decode(tlv_len: u8, buf: &mut Bytes) -> DecodeResult<Self> {
// Validate the TLV length.
if tlv_len as usize != Self::SIZE {
return Err(DecodeError::InvalidTlvLength(tlv_len));
}

let size = buf.get_u16();

Ok(LspBufferSizeTlv { size })
}

pub(crate) fn encode(&self, buf: &mut BytesMut) {
let start_pos = tlv_encode_start(buf, TlvType::LspBufferSize);
buf.put_u16(self.size);
tlv_encode_end(buf, start_pos);
}
}

impl Tlv for LspBufferSizeTlv {
fn len(&self) -> usize {
TLV_HDR_SIZE + Self::SIZE
}
}

// ===== impl ProtocolsSupportedTlv =====

impl ProtocolsSupportedTlv {
Expand Down
24 changes: 13 additions & 11 deletions holo-isis/tests/packet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ use holo_isis::packet::pdu::{
use holo_isis::packet::tlv::{
AreaAddressesTlv, ExtIpv4Reach, ExtIpv4ReachTlv, ExtIsReach, ExtIsReachTlv,
Ipv4AddressesTlv, Ipv4Reach, Ipv4ReachTlv, Ipv6AddressesTlv, Ipv6Reach,
Ipv6ReachTlv, IsReach, IsReachTlv, LspEntriesTlv, LspEntry, NeighborsTlv,
PaddingTlv, ProtocolsSupportedTlv,
Ipv6ReachTlv, IsReach, IsReachTlv, LspBufferSizeTlv, LspEntriesTlv,
LspEntry, NeighborsTlv, PaddingTlv, ProtocolsSupportedTlv,
};
use holo_isis::packet::{
AreaAddr, LanId, LevelNumber, LevelType, LspId, SystemId,
Expand Down Expand Up @@ -547,6 +547,7 @@ static LSP1: Lazy<(Vec<u8>, Pdu)> = Lazy::new(|| {
area_addrs: vec![AreaAddressesTlv {
list: vec![AreaAddr::from([0x49, 0, 0].as_slice())],
}],
lsp_buf_size: None,
is_reach: vec![],
ext_is_reach: vec![ExtIsReachTlv {
list: vec![ExtIsReach {
Expand Down Expand Up @@ -614,16 +615,16 @@ static LSP1: Lazy<(Vec<u8>, Pdu)> = Lazy::new(|| {
static LSP2: Lazy<(Vec<u8>, Pdu)> = Lazy::new(|| {
(
vec![
0x83, 0x1b, 0x01, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x69, 0x04,
0x83, 0x1b, 0x01, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x6d, 0x04,
0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x13, 0x06, 0xe2, 0x01, 0x81, 0x01, 0xcc, 0x01, 0x04, 0x03,
0x49, 0x00, 0x00, 0x02, 0x17, 0x00, 0x0a, 0x80, 0x80, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x80, 0x80, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x84, 0x04, 0x06, 0x06, 0x06,
0x06, 0x80, 0x24, 0x0a, 0x80, 0x80, 0x80, 0x0a, 0x00, 0x07, 0x00,
0xff, 0xff, 0xff, 0x00, 0x0a, 0x80, 0x80, 0x80, 0x0a, 0x00, 0x08,
0x00, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x80, 0x80, 0x80, 0x06, 0x06,
0x06, 0x06, 0xff, 0xff, 0xff, 0xff,
0x00, 0x13, 0x0f, 0xef, 0x01, 0x81, 0x01, 0xcc, 0x01, 0x04, 0x03,
0x49, 0x00, 0x00, 0x0e, 0x02, 0x05, 0xd4, 0x02, 0x17, 0x00, 0x0a,
0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0a,
0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x84,
0x04, 0x06, 0x06, 0x06, 0x06, 0x80, 0x24, 0x0a, 0x80, 0x80, 0x80,
0x0a, 0x00, 0x07, 0x00, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x80, 0x80,
0x80, 0x0a, 0x00, 0x08, 0x00, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x80,
0x80, 0x80, 0x06, 0x06, 0x06, 0x06, 0xff, 0xff, 0xff, 0xff,
],
Pdu::Lsp(Lsp::new(
LevelNumber::L1,
Expand All @@ -638,6 +639,7 @@ static LSP2: Lazy<(Vec<u8>, Pdu)> = Lazy::new(|| {
area_addrs: vec![AreaAddressesTlv {
list: vec![AreaAddr::from([0x49, 0, 0].as_slice())],
}],
lsp_buf_size: Some(LspBufferSizeTlv { size: 1492 }),
is_reach: vec![IsReachTlv {
list: vec![
IsReach {
Expand Down
13 changes: 13 additions & 0 deletions holo-yang/modules/augmentations/holo-isis.yang
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,17 @@ module holo-isis {
"Interface circuit ID.";
}
}


augment "/rt:routing/rt:control-plane-protocols/"
+ "rt:control-plane-protocol/isis:isis/isis:database/"
+ "isis:levels/isis:lsp" {
leaf lsp-buffer-size {
type uint16;
units "bytes";
description
"The maximum sized LSP which may be generated.
The IS-IS reference is TLV 14.";
}
}
}

0 comments on commit 4a01363

Please sign in to comment.