Skip to content

Commit

Permalink
isis: implement the Dynamic Hostname TLV
Browse files Browse the repository at this point in the history
Signed-off-by: Renato Westphal <[email protected]>
  • Loading branch information
rwestphal committed Jan 4, 2025
1 parent 4a01363 commit 4c11772
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 21 deletions.
17 changes: 16 additions & 1 deletion holo-isis/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::collections::{
};
use crate::debug::{Debug, LspPurgeReason};
use crate::error::{AdjacencyRejectError, Error};
use crate::instance::{InstanceArenas, InstanceUpView};
use crate::instance::{Instance, InstanceArenas, InstanceUpView};
use crate::interface::InterfaceType;
use crate::lsdb::{self, lsp_compare, LspEntryFlags};
use crate::northbound::notification;
Expand Down Expand Up @@ -1193,3 +1193,18 @@ pub(crate) fn process_spf_delay_event(
// Trigger SPF Delay FSM event.
spf::fsm(level, event, instance, arenas)
}

// ===== Hostname update event =====

pub(crate) fn process_hostname_update(
instance: &mut Instance,
hostname: Option<String>,
) {
// Update hostname.
instance.shared.hostname = hostname;

// Schedule LSP reorigination.
if let Some((mut instance, _)) = instance.as_up() {
instance.schedule_lsp_origination(instance.config.level_type);
}
}
4 changes: 4 additions & 0 deletions holo-isis/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,10 @@ async fn process_ibus_msg(
IbusMsg::InterfaceAddressDel(msg) => {
southbound::rx::process_addr_del(instance, msg);
}
// Hostname update notification.
IbusMsg::HostnameUpdate(hostname) => {
events::process_hostname_update(instance, hostname);
}
// Ignore other events.
_ => {}
}
Expand Down
16 changes: 15 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(),
instance.shared.hostname.clone(),
Some(instance.config.lsp_mtu),
is_reach,
ext_is_reach,
Expand Down Expand Up @@ -361,7 +362,20 @@ fn lsp_build_tlvs_pseudo(
}
}

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

fn lsp_build_fragments(
Expand Down
2 changes: 1 addition & 1 deletion holo-isis/src/northbound/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ fn load_callbacks() -> Callbacks<Instance> {
ipv4_te_routerid: None,
ipv6_te_routerid: None,
protocol_supported: Some(Box::new(protocol_supported)),
dynamic_hostname: None,
dynamic_hostname: lsp.tlvs.hostname().map(Cow::Borrowed),
lsp_buffer_size: lsp.tlvs.lsp_buf_size(),
})
})
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 @@ -55,6 +55,7 @@ pub enum TlvType {
Ipv4ExternalReach = 130,
Ipv4Addresses = 132,
ExtIpv4Reach = 135,
DynamicHostname = 137,
Ipv6Addresses = 232,
Ipv6Reach = 236,
}
Expand Down
32 changes: 27 additions & 5 deletions holo-isis/src/packet/pdu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ use crate::packet::consts::{
};
use crate::packet::error::{DecodeError, DecodeResult};
use crate::packet::tlv::{
tlv_entries_split, tlv_take_max, AreaAddressesTlv, ExtIpv4Reach,
ExtIpv4ReachTlv, ExtIsReach, ExtIsReachTlv, Ipv4AddressesTlv, Ipv4Reach,
Ipv4ReachTlv, Ipv6AddressesTlv, Ipv6Reach, Ipv6ReachTlv, IsReach,
IsReachTlv, LspBufferSizeTlv, LspEntriesTlv, LspEntry, NeighborsTlv,
PaddingTlv, ProtocolsSupportedTlv, Tlv, UnknownTlv, TLV_HDR_SIZE,
tlv_entries_split, tlv_take_max, AreaAddressesTlv, DynamicHostnameTlv,
ExtIpv4Reach, ExtIpv4ReachTlv, ExtIsReach, ExtIsReachTlv, Ipv4AddressesTlv,
Ipv4Reach, Ipv4ReachTlv, Ipv6AddressesTlv, Ipv6Reach, Ipv6ReachTlv,
IsReach, 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 +103,7 @@ pub struct Lsp {
pub struct LspTlvs {
pub protocols_supported: Option<ProtocolsSupportedTlv>,
pub area_addrs: Vec<AreaAddressesTlv>,
pub hostname: Option<DynamicHostnameTlv>,
pub lsp_buf_size: Option<LspBufferSizeTlv>,
pub is_reach: Vec<IsReachTlv>,
pub ext_is_reach: Vec<ExtIsReachTlv>,
Expand Down Expand Up @@ -601,6 +603,11 @@ impl Lsp {
let tlv = AreaAddressesTlv::decode(tlv_len, &mut buf_tlv)?;
tlvs.area_addrs.push(tlv);
}
Some(TlvType::DynamicHostname) => {
let tlv =
DynamicHostnameTlv::decode(tlv_len, &mut buf_tlv)?;
tlvs.hostname = Some(tlv);
}
Some(TlvType::LspBufferSize) => {
let tlv = LspBufferSizeTlv::decode(tlv_len, &mut buf_tlv)?;
tlvs.lsp_buf_size = Some(tlv);
Expand Down Expand Up @@ -688,6 +695,9 @@ impl Lsp {
for tlv in &self.tlvs.area_addrs {
tlv.encode(&mut buf);
}
if let Some(tlv) = &self.tlvs.hostname {
tlv.encode(&mut buf);
}
if let Some(tlv) = &self.tlvs.lsp_buf_size {
tlv.encode(&mut buf);
}
Expand Down Expand Up @@ -815,6 +825,7 @@ impl LspTlvs {
pub(crate) fn new(
protocols_supported: impl IntoIterator<Item = u8>,
area_addrs: impl IntoIterator<Item = AreaAddr>,
hostname: Option<String>,
lsp_buf_size: Option<u16>,
is_reach: impl IntoIterator<Item = IsReach>,
ext_is_reach: impl IntoIterator<Item = ExtIsReach>,
Expand All @@ -830,6 +841,7 @@ impl LspTlvs {
protocols_supported,
)),
area_addrs: tlv_entries_split(area_addrs),
hostname: hostname.map(|hostname| DynamicHostnameTlv { hostname }),
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),
Expand All @@ -850,6 +862,10 @@ impl LspTlvs {
rem_len -= protocols_supported.len();
}
let area_addrs = tlv_take_max(&mut self.area_addrs, &mut rem_len);
let hostname = self.hostname.take();
if let Some(hostname) = &hostname {
rem_len -= hostname.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();
Expand All @@ -872,6 +888,7 @@ impl LspTlvs {
Some(LspTlvs {
protocols_supported,
area_addrs,
hostname,
lsp_buf_size,
is_reach,
ext_is_reach,
Expand Down Expand Up @@ -899,6 +916,11 @@ impl LspTlvs {
self.area_addrs.iter().flat_map(|tlv| tlv.list.iter())
}

// Returns the dynamic hostname (TLV type 137).
pub(crate) fn hostname(&self) -> Option<&str> {
self.hostname.as_ref().map(|tlv| tlv.hostname.as_str())
}

// 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)
Expand Down
37 changes: 37 additions & 0 deletions holo-isis/src/packet/tlv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ pub struct LspBufferSizeTlv {
pub size: u16,
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct DynamicHostnameTlv {
pub hostname: String,
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct ProtocolsSupportedTlv {
Expand Down Expand Up @@ -394,6 +400,37 @@ impl Tlv for LspBufferSizeTlv {
}
}

// ===== impl DynamicHostnameTlv =====

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

let mut hostname_bytes = [0; 255];
buf.copy_to_slice(&mut hostname_bytes[..tlv_len as usize]);
let hostname =
String::from_utf8_lossy(&hostname_bytes[..tlv_len as usize])
.to_string();

Ok(DynamicHostnameTlv { hostname })
}

pub(crate) fn encode(&self, buf: &mut BytesMut) {
let start_pos = tlv_encode_start(buf, TlvType::DynamicHostname);
buf.put_slice(self.hostname.as_bytes());
tlv_encode_end(buf, start_pos);
}
}

impl Tlv for DynamicHostnameTlv {
fn len(&self) -> usize {
TLV_HDR_SIZE + self.hostname.len()
}
}

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

impl ProtocolsSupportedTlv {
Expand Down
32 changes: 19 additions & 13 deletions holo-isis/tests/packet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ use holo_isis::packet::pdu::{
Hello, HelloTlvs, HelloVariant, Lsp, LspTlvs, Pdu, Snp, SnpTlvs,
};
use holo_isis::packet::tlv::{
AreaAddressesTlv, ExtIpv4Reach, ExtIpv4ReachTlv, ExtIsReach, ExtIsReachTlv,
Ipv4AddressesTlv, Ipv4Reach, Ipv4ReachTlv, Ipv6AddressesTlv, Ipv6Reach,
Ipv6ReachTlv, IsReach, IsReachTlv, LspBufferSizeTlv, LspEntriesTlv,
LspEntry, NeighborsTlv, PaddingTlv, ProtocolsSupportedTlv,
AreaAddressesTlv, DynamicHostnameTlv, ExtIpv4Reach, ExtIpv4ReachTlv,
ExtIsReach, ExtIsReachTlv, Ipv4AddressesTlv, Ipv4Reach, Ipv4ReachTlv,
Ipv6AddressesTlv, Ipv6Reach, 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 +548,7 @@ static LSP1: Lazy<(Vec<u8>, Pdu)> = Lazy::new(|| {
area_addrs: vec![AreaAddressesTlv {
list: vec![AreaAddr::from([0x49, 0, 0].as_slice())],
}],
hostname: None,
lsp_buf_size: None,
is_reach: vec![],
ext_is_reach: vec![ExtIsReachTlv {
Expand Down Expand Up @@ -615,16 +617,17 @@ 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, 0x6d, 0x04,
0x83, 0x1b, 0x01, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x73, 0x04,
0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
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,
0x00, 0x13, 0x84, 0x39, 0x01, 0x81, 0x01, 0xcc, 0x01, 0x04, 0x03,
0x49, 0x00, 0x00, 0x89, 0x04, 0x68, 0x6f, 0x6c, 0x6f, 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 @@ -639,6 +642,9 @@ static LSP2: Lazy<(Vec<u8>, Pdu)> = Lazy::new(|| {
area_addrs: vec![AreaAddressesTlv {
list: vec![AreaAddr::from([0x49, 0, 0].as_slice())],
}],
hostname: Some(DynamicHostnameTlv {
hostname: "holo".to_owned(),
}),
lsp_buf_size: Some(LspBufferSizeTlv { size: 1492 }),
is_reach: vec![IsReachTlv {
list: vec![
Expand Down
2 changes: 2 additions & 0 deletions holo-protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ where
pub struct InstanceShared {
// Non-volatile storage.
pub db: Option<Database>,
// Hostname.
pub hostname: Option<String>,
// MPLS Label Manager.
pub label_manager: Arc<Mutex<LabelManager>>,
// List of key-chains.
Expand Down

0 comments on commit 4c11772

Please sign in to comment.