-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
isis: add support for IS reachability TE Sub-TLVs
This commit implements the encoding and decoding routines for the IS reachability TE Sub-TLVs as defined in section 3 of RFC 5305. Additionally, these TE Sub-TLVs are visible as part of YANG-modeled state data. Configuration and announcement of these attributes are not yet supported. Example operational data (JSON output): ``` { "extended-is-neighbor": { "neighbor": [ { "neighbor-id": "0000.0001.0003.01", "instances": { "instance": [ { "id": 0, "metric": 10, "admin-group": 171, "local-if-ipv4-addrs": { "local-if-ipv4-addr": [ "10.0.1.1" ] }, "remote-if-ipv4-addrs": { "remote-if-ipv4-addr": [ "10.0.1.2" ] }, "te-metric": 100, "max-bandwidth": "0x1.3ebc20p+23", "max-reservable-bandwidth": "0x1.189680p+20", "unreserved-bandwidths": { "unreserved-bandwidth": [ { "priority": 0, "unreserved-bandwidth": "0x1.189680p+20" }, { "priority": 1, "unreserved-bandwidth": "0x1.189680p+20" }, { "priority": 2, "unreserved-bandwidth": "0x1.189680p+20" }, { "priority": 3, "unreserved-bandwidth": "0x1.189680p+20" }, { "priority": 4, "unreserved-bandwidth": "0x1.189680p+20" }, { "priority": 5, "unreserved-bandwidth": "0x1.189680p+20" }, { "priority": 6, "unreserved-bandwidth": "0x1.189680p+20" }, { "priority": 7, "unreserved-bandwidth": "0x1.189680p+20" } ] } } ] } } ] } } ``` Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
- Loading branch information
Showing
8 changed files
with
488 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// | ||
// Copyright (c) The Holo Core Contributors | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
// Sponsored by NLnet as part of the Next Generation Internet initiative. | ||
// See: https://nlnet.nl/NGI0 | ||
// | ||
|
||
pub mod neighbor; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
// | ||
// Copyright (c) The Holo Core Contributors | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
// Sponsored by NLnet as part of the Next Generation Internet initiative. | ||
// See: https://nlnet.nl/NGI0 | ||
// | ||
|
||
use std::net::Ipv4Addr; | ||
|
||
use bytes::{Buf, BufMut, Bytes, BytesMut}; | ||
use derive_new::new; | ||
use holo_utils::bytes::{BytesExt, BytesMutExt}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
use crate::packet::consts::NeighborSubTlvType; | ||
use crate::packet::error::{DecodeError, DecodeResult}; | ||
use crate::packet::tlv::{tlv_encode_end, tlv_encode_start}; | ||
|
||
#[derive(Clone, Debug, Eq, PartialEq)] | ||
#[derive(new)] | ||
#[derive(Deserialize, Serialize)] | ||
pub struct AdminGroupSubTlv(u32); | ||
|
||
#[derive(Clone, Debug, Eq, PartialEq)] | ||
#[derive(new)] | ||
#[derive(Deserialize, Serialize)] | ||
pub struct Ipv4InterfaceAddrSubTlv(Ipv4Addr); | ||
|
||
#[derive(Clone, Debug, Eq, PartialEq)] | ||
#[derive(new)] | ||
#[derive(Deserialize, Serialize)] | ||
pub struct Ipv4NeighborAddrSubTlv(Ipv4Addr); | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
#[derive(new)] | ||
#[derive(Deserialize, Serialize)] | ||
pub struct MaxLinkBwSubTlv(f32); | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
#[derive(new)] | ||
#[derive(Deserialize, Serialize)] | ||
pub struct MaxResvLinkBwSubTlv(f32); | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
#[derive(new)] | ||
#[derive(Deserialize, Serialize)] | ||
pub struct UnreservedBwSubTlv([f32; 8]); | ||
|
||
#[derive(Clone, Debug, Eq, PartialEq)] | ||
#[derive(new)] | ||
#[derive(Deserialize, Serialize)] | ||
pub struct TeDefaultMetricSubTlv(u32); | ||
|
||
// ===== impl AdminGroupSubTlv ===== | ||
|
||
impl AdminGroupSubTlv { | ||
const SIZE: usize = 4; | ||
|
||
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 groups = buf.get_u32(); | ||
|
||
Ok(AdminGroupSubTlv(groups)) | ||
} | ||
|
||
pub(crate) fn encode(&self, buf: &mut BytesMut) { | ||
let start_pos = tlv_encode_start(buf, NeighborSubTlvType::AdminGroup); | ||
buf.put_u32(self.0); | ||
tlv_encode_end(buf, start_pos); | ||
} | ||
|
||
pub(crate) fn get(&self) -> u32 { | ||
self.0 | ||
} | ||
} | ||
|
||
// ===== impl Ipv4InterfaceAddrSubTlv ===== | ||
|
||
impl Ipv4InterfaceAddrSubTlv { | ||
const SIZE: usize = 4; | ||
|
||
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 addr = buf.get_ipv4(); | ||
|
||
Ok(Ipv4InterfaceAddrSubTlv(addr)) | ||
} | ||
|
||
pub(crate) fn encode(&self, buf: &mut BytesMut) { | ||
let start_pos = | ||
tlv_encode_start(buf, NeighborSubTlvType::Ipv4InterfaceAddress); | ||
buf.put_ipv4(&self.0); | ||
tlv_encode_end(buf, start_pos); | ||
} | ||
|
||
pub(crate) fn get(&self) -> &Ipv4Addr { | ||
&self.0 | ||
} | ||
} | ||
|
||
// ===== impl Ipv4NeighborAddrSubTlv ===== | ||
|
||
impl Ipv4NeighborAddrSubTlv { | ||
const SIZE: usize = 4; | ||
|
||
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 addr = buf.get_ipv4(); | ||
|
||
Ok(Ipv4NeighborAddrSubTlv(addr)) | ||
} | ||
|
||
pub(crate) fn encode(&self, buf: &mut BytesMut) { | ||
let start_pos = | ||
tlv_encode_start(buf, NeighborSubTlvType::Ipv4NeighborAddress); | ||
buf.put_ipv4(&self.0); | ||
tlv_encode_end(buf, start_pos); | ||
} | ||
|
||
pub(crate) fn get(&self) -> &Ipv4Addr { | ||
&self.0 | ||
} | ||
} | ||
|
||
// ===== impl MaxLinkBwSubTlv ===== | ||
|
||
impl MaxLinkBwSubTlv { | ||
const SIZE: usize = 4; | ||
|
||
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 bw = buf.get_f32(); | ||
|
||
Ok(MaxLinkBwSubTlv(bw)) | ||
} | ||
|
||
pub(crate) fn encode(&self, buf: &mut BytesMut) { | ||
let start_pos = | ||
tlv_encode_start(buf, NeighborSubTlvType::MaxLinkBandwidth); | ||
buf.put_f32(self.0); | ||
tlv_encode_end(buf, start_pos); | ||
} | ||
|
||
pub(crate) fn get(&self) -> &f32 { | ||
&self.0 | ||
} | ||
} | ||
|
||
// ===== impl MaxResvLinkBwSubTlv ===== | ||
|
||
impl MaxResvLinkBwSubTlv { | ||
const SIZE: usize = 4; | ||
|
||
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 bw = buf.get_f32(); | ||
|
||
Ok(MaxResvLinkBwSubTlv(bw)) | ||
} | ||
|
||
pub(crate) fn encode(&self, buf: &mut BytesMut) { | ||
let start_pos = | ||
tlv_encode_start(buf, NeighborSubTlvType::MaxResvLinkBandwidth); | ||
buf.put_f32(self.0); | ||
tlv_encode_end(buf, start_pos); | ||
} | ||
|
||
pub(crate) fn get(&self) -> &f32 { | ||
&self.0 | ||
} | ||
} | ||
|
||
// ===== impl UnreservedBwSubTlv ===== | ||
|
||
impl UnreservedBwSubTlv { | ||
const SIZE: usize = 32; | ||
|
||
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 mut bws = [0f32; 8]; | ||
for bw in &mut bws { | ||
*bw = buf.get_f32(); | ||
} | ||
|
||
Ok(UnreservedBwSubTlv(bws)) | ||
} | ||
|
||
pub(crate) fn encode(&self, buf: &mut BytesMut) { | ||
let start_pos = | ||
tlv_encode_start(buf, NeighborSubTlvType::UnreservedBandwidth); | ||
for bw in &self.0 { | ||
buf.put_f32(*bw); | ||
} | ||
tlv_encode_end(buf, start_pos); | ||
} | ||
|
||
pub(crate) fn iter(&self) -> impl Iterator<Item = (usize, &f32)> { | ||
self.0.iter().enumerate() | ||
} | ||
} | ||
|
||
// ===== impl TeDefaultMetricSubTlv ===== | ||
|
||
impl TeDefaultMetricSubTlv { | ||
const SIZE: usize = 3; | ||
|
||
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 metric = buf.get_u24(); | ||
|
||
Ok(TeDefaultMetricSubTlv(metric)) | ||
} | ||
|
||
pub(crate) fn encode(&self, buf: &mut BytesMut) { | ||
let start_pos = | ||
tlv_encode_start(buf, NeighborSubTlvType::TeDefaultMetric); | ||
buf.put_u24(self.0); | ||
tlv_encode_end(buf, start_pos); | ||
} | ||
|
||
pub(crate) fn get(&self) -> u32 { | ||
self.0 | ||
} | ||
} |
Oops, something went wrong.