diff --git a/README.md b/README.md index 774a83ed..390b4824 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,7 @@ Holo supports the following Internet Standards: * RFC 5243 - OSPF Database Exchange Summary List Optimization * RFC 5250 - The OSPF Opaque LSA Option * RFC 5340 - OSPF for IPv6 +* RFC 5642 - Dynamic Hostname Exchange Mechanism for OSPF * RFC 5709 - OSPFv2 HMAC-SHA Cryptographic Authentication * RFC 5838 - Support of Address Families in OSPFv3 * RFC 6987 - OSPF Stub Router Advertisement diff --git a/holo-ospf/src/events.rs b/holo-ospf/src/events.rs index e0e5884d..f0a62796 100644 --- a/holo-ospf/src/events.rs +++ b/holo-ospf/src/events.rs @@ -1526,3 +1526,25 @@ where Ok(()) } + +// ===== Hostname update event ===== + +pub(crate) fn process_hostname_update( + instance: &mut Instance, + hostname: Option, +) -> Result<(), Error> +where + V: Version, +{ + instance.shared.hostname = hostname; + + if let Some((instance, arenas)) = instance.as_up() { + V::lsa_orig_event( + &instance, + arenas, + LsaOriginateEvent::HostnameChange, + )?; + } + + Ok(()) +} diff --git a/holo-ospf/src/instance.rs b/holo-ospf/src/instance.rs index 3a516637..67381ff5 100644 --- a/holo-ospf/src/instance.rs +++ b/holo-ospf/src/instance.rs @@ -103,6 +103,8 @@ pub struct InstanceState { pub gr_helper_count: usize, // Authentication non-decreasing sequence number. pub auth_seqno: Arc, + // Hostname cache. + pub hostnames: BTreeMap, } #[derive(Debug, Default)] @@ -580,6 +582,7 @@ where spf_log_next_id: 0, gr_helper_count: 0, auth_seqno: Arc::new(V::initial_auth_seqno(boot_count).into()), + hostnames: Default::default(), } } } @@ -791,6 +794,9 @@ where IbusMsg::BierCfgEvent(event) => { events::process_bier_cfg_change(instance, event)? } + IbusMsg::HostnameUpdate(hostname) => { + events::process_hostname_update(instance, hostname)?; + } // Ignore other events. _ => {} } diff --git a/holo-ospf/src/lsdb.rs b/holo-ospf/src/lsdb.rs index faa37fb1..2fb9c1c9 100644 --- a/holo-ospf/src/lsdb.rs +++ b/holo-ospf/src/lsdb.rs @@ -128,6 +128,7 @@ pub enum LsaOriginateEvent { BierCfgChange { change: BierCfgEvent, }, + HostnameChange, } #[derive(Debug)] @@ -211,7 +212,7 @@ pub trait LsdbVersion { // Custom LSA installation handling. fn lsdb_install( - instance: &InstanceUpView<'_, V>, + instance: &mut InstanceUpView<'_, V>, arenas: &mut InstanceArenas, lsdb_idx: LsdbIndex, lsdb_id: LsdbId, diff --git a/holo-ospf/src/northbound/state.rs b/holo-ospf/src/northbound/state.rs index 0da97394..23e28910 100644 --- a/holo-ospf/src/northbound/state.rs +++ b/holo-ospf/src/northbound/state.rs @@ -51,6 +51,7 @@ pub enum ListEntry<'a, V: Version> { LsaLog(&'a LsaLogEntry), Route(&'a V::IpNetwork, &'a RouteNet), Nexthop(&'a Nexthop), + Hostname(&'a Ipv4Addr, &'a String), AsStatsLsaType(&'a LsdbSingleType), AsLsaType(&'a LsdbSingleType), AsLsa(&'a LsaEntry), @@ -536,6 +537,20 @@ where raw_data: Some(lsa.raw.as_ref()).ignore_in_testing(), }) }) + .path(ospf::hostnames::hostname::PATH) + .get_iterate(|instance, _args| { + let Some(instance_state) = &instance.state else { return None }; + let iter = instance_state.hostnames.iter().map(|(router_id, hostname)| ListEntry::Hostname(router_id, hostname)); + Some(Box::new(iter) as _) + }) + .get_object(|_instance, args| { + use ospf::hostnames::hostname::Hostname; + let (router_id, hostname) = args.list_entry.as_hostname().unwrap(); + Box::new(Hostname { + router_id: Cow::Borrowed(router_id), + hostname: Some(Cow::Borrowed(hostname)), + }) + }) .build() } @@ -662,6 +677,21 @@ fn load_callbacks_ospfv2() -> Callbacks> { functional_flag: Some(*flag), }) }) + .path(ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv2::body::opaque::ri_opaque::dynamic_hostname_tlv::PATH) + .get_object(|_instance, args| { + use ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv2::body::opaque::ri_opaque::dynamic_hostname_tlv::DynamicHostnameTlv; + let lse: &LsaEntry = args.list_entry.as_as_lsa().unwrap(); + let lsa = &lse.data; + let mut hostname = None; + if let Some(lsa_body) = lsa.body.as_opaque_as() + && let Some(lsa_body) = lsa_body.as_router_info() + && let Some(info_hostname) = &lsa_body.info_hostname { + hostname = Some(Cow::Borrowed(info_hostname.get())); + } + Box::new(DynamicHostnameTlv { + hostname, + }) + }) .path(ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv2::body::opaque::ri_opaque::maximum_sid_depth_tlv::msd_type::PATH) .get_iterate(|_instance, args| { let lse: &LsaEntry = args.parent_list_entry.as_as_lsa().unwrap(); @@ -1066,6 +1096,21 @@ fn load_callbacks_ospfv2() -> Callbacks> { functional_flag: Some(*flag), }) }) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv2::body::opaque::ri_opaque::dynamic_hostname_tlv::PATH) + .get_object(|_instance, args| { + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv2::body::opaque::ri_opaque::dynamic_hostname_tlv::DynamicHostnameTlv; + let lse: &LsaEntry = args.list_entry.as_area_lsa().unwrap(); + let lsa = &lse.data; + let mut hostname = None; + if let Some(lsa_body) = lsa.body.as_opaque_area() + && let Some(lsa_body) = lsa_body.as_router_info() + && let Some(info_hostname) = &lsa_body.info_hostname { + hostname = Some(Cow::Borrowed(info_hostname.get())); + } + Box::new(DynamicHostnameTlv { + hostname, + }) + }) .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv2::body::opaque::ri_opaque::maximum_sid_depth_tlv::msd_type::PATH) .get_iterate(|_instance, args| { let lse: &LsaEntry = args.parent_list_entry.as_area_lsa().unwrap(); @@ -1783,6 +1828,20 @@ fn load_callbacks_ospfv3() -> Callbacks> { functional_flag: Some(*flag), }) }) + .path(ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::router_information::dynamic_hostname_tlv::PATH) + .get_object(|_instance, args| { + use ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::router_information::dynamic_hostname_tlv::DynamicHostnameTlv; + let lse: &LsaEntry = args.list_entry.as_as_lsa().unwrap(); + let lsa = &lse.data; + let mut hostname = None; + if let Some(lsa_body) = lsa.body.as_router_info() + && let Some(info_hostname) = &lsa_body.info_hostname { + hostname = Some(Cow::Borrowed(info_hostname.get())); + } + Box::new(DynamicHostnameTlv { + hostname, + }) + }) .path(ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::router_information::sr_algorithm_tlv::PATH) .get_object(|_instance, args| { use ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::router_information::sr_algorithm_tlv::SrAlgorithmTlv; @@ -2250,6 +2309,20 @@ fn load_callbacks_ospfv3() -> Callbacks> { functional_flag: Some(*flag), }) }) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::router_information::dynamic_hostname_tlv::PATH) + .get_object(|_instance, args| { + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::router_information::dynamic_hostname_tlv::DynamicHostnameTlv; + let lse: &LsaEntry = args.list_entry.as_area_lsa().unwrap(); + let lsa = &lse.data; + let mut hostname = None; + if let Some(lsa_body) = lsa.body.as_router_info() + && let Some(info_hostname) = &lsa_body.info_hostname { + hostname = Some(Cow::Borrowed(info_hostname.get())); + } + Box::new(DynamicHostnameTlv { + hostname, + }) + }) .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::router_information::sr_algorithm_tlv::PATH) .get_object(|_instance, args| { use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::router_information::sr_algorithm_tlv::SrAlgorithmTlv; diff --git a/holo-ospf/src/ospfv2/lsdb.rs b/holo-ospf/src/ospfv2/lsdb.rs index 01eb4ea0..ecb95ef5 100644 --- a/holo-ospf/src/ospfv2/lsdb.rs +++ b/holo-ospf/src/ospfv2/lsdb.rs @@ -38,8 +38,8 @@ use crate::packet::lsa::{ Lsa, LsaHdrVersion, LsaKey, LsaScope, LsaTypeVersion, }; use crate::packet::tlv::{ - PrefixSidFlags, RouterInfoCaps, RouterInfoCapsTlv, SidLabelRangeTlv, - SrAlgoTlv, SrLocalBlockTlv, + DynamicHostnameTlv, PrefixSidFlags, RouterInfoCaps, RouterInfoCapsTlv, + SidLabelRangeTlv, SrAlgoTlv, SrLocalBlockTlv, }; use crate::route::{SummaryNet, SummaryRtr}; use crate::version::Ospfv2; @@ -240,6 +240,12 @@ impl LsdbVersion for Ospfv2 { } } } + LsaOriginateEvent::HostnameChange => { + // (Re)originate Router Information LSA(s) in all areas. + for area in arenas.areas.iter() { + lsa_orig_router_info(area, instance); + } + } _ => (), }; @@ -321,7 +327,7 @@ impl LsdbVersion for Ospfv2 { } fn lsdb_install( - instance: &InstanceUpView<'_, Self>, + instance: &mut InstanceUpView<'_, Self>, arenas: &mut InstanceArenas, lsdb_idx: LsdbIndex, _lsdb_id: LsdbId, @@ -346,6 +352,22 @@ impl LsdbVersion for Ospfv2 { } } } + + // Update hostname database. + if let LsaBody::OpaqueArea(LsaOpaque::RouterInfo(router_info)) + | LsaBody::OpaqueAs(LsaOpaque::RouterInfo(router_info)) = &lsa.body + { + if let Some(hostname_tlv) = router_info.info_hostname.as_ref() { + // Install or update hostname. + instance + .state + .hostnames + .insert(lsa.hdr.adv_rtr, hostname_tlv.hostname.clone()); + } else { + // Remove hostname if it exists. + instance.state.hostnames.remove(&lsa.hdr.adv_rtr); + } + } } } @@ -595,6 +617,11 @@ fn lsa_orig_router_info( srlb, msds: None, srms_pref: None, + info_hostname: instance + .shared + .hostname + .as_ref() + .map(|hostname| DynamicHostnameTlv::new(hostname.to_string())), unknown_tlvs: vec![], })); instance.tx.protocol_input.lsa_orig_check( diff --git a/holo-ospf/src/ospfv2/packet/lsa_opaque.rs b/holo-ospf/src/ospfv2/packet/lsa_opaque.rs index 7d28686a..b82669d9 100644 --- a/holo-ospf/src/ospfv2/packet/lsa_opaque.rs +++ b/holo-ospf/src/ospfv2/packet/lsa_opaque.rs @@ -23,10 +23,10 @@ use crate::ospfv2::packet::lsa::{LsaRouterLinkType, LsaUnknown}; use crate::packet::error::{DecodeError, DecodeResult}; use crate::packet::lsa::{AdjSidVersion, PrefixSidVersion}; use crate::packet::tlv::{ - tlv_encode_end, tlv_encode_start, tlv_wire_len, AdjSidFlags, GrReasonTlv, - GracePeriodTlv, MsdTlv, PrefixSidFlags, RouterFuncCapsTlv, - RouterInfoCapsTlv, RouterInfoTlvType, SidLabelRangeTlv, SrAlgoTlv, - SrLocalBlockTlv, SrmsPrefTlv, UnknownTlv, TLV_HDR_SIZE, + tlv_encode_end, tlv_encode_start, tlv_wire_len, AdjSidFlags, + DynamicHostnameTlv, GrReasonTlv, GracePeriodTlv, MsdTlv, PrefixSidFlags, + RouterFuncCapsTlv, RouterInfoCapsTlv, RouterInfoTlvType, SidLabelRangeTlv, + SrAlgoTlv, SrLocalBlockTlv, SrmsPrefTlv, UnknownTlv, TLV_HDR_SIZE, }; // OSPFv2 opaque LSA types. @@ -122,6 +122,8 @@ pub struct LsaRouterInfo { pub srlb: Vec, pub msds: Option, pub srms_pref: Option, + #[serde(skip)] + pub info_hostname: Option, pub unknown_tlvs: Vec, } @@ -544,6 +546,11 @@ impl LsaRouterInfo { RouterFuncCapsTlv::decode(tlv_len, &mut buf_tlv)?; router_info.func_caps.get_or_insert(caps); } + Some(RouterInfoTlvType::DynamicHostname) => { + let hostname = + DynamicHostnameTlv::decode(tlv_len, &mut buf_tlv)?; + router_info.info_hostname.get_or_insert(hostname); + } Some(RouterInfoTlvType::SrAlgo) => { let sr_algo = SrAlgoTlv::decode(tlv_len, &mut buf_tlv)?; router_info.sr_algo.get_or_insert(sr_algo); @@ -584,6 +591,9 @@ impl LsaRouterInfo { if let Some(func_caps) = &self.func_caps { func_caps.encode(buf); } + if let Some(info_hostname) = &self.info_hostname { + info_hostname.encode(buf); + } if let Some(sr_algo) = &self.sr_algo { sr_algo.encode(buf); } diff --git a/holo-ospf/src/ospfv3/lsdb.rs b/holo-ospf/src/ospfv3/lsdb.rs index f715e295..3806e540 100644 --- a/holo-ospf/src/ospfv3/lsdb.rs +++ b/holo-ospf/src/ospfv3/lsdb.rs @@ -36,9 +36,9 @@ use crate::packet::lsa::{ Lsa, LsaHdrVersion, LsaKey, LsaScope, LsaTypeVersion, PrefixSidVersion, }; use crate::packet::tlv::{ - BierEncapId, BierEncapSubSubTlv, BierSubSubTlv, BierSubTlv, PrefixSidFlags, - RouterInfoCaps, RouterInfoCapsTlv, SidLabelRangeTlv, SrAlgoTlv, - SrLocalBlockTlv, + BierEncapId, BierEncapSubSubTlv, BierSubSubTlv, BierSubTlv, + DynamicHostnameTlv, PrefixSidFlags, RouterInfoCaps, RouterInfoCapsTlv, + SidLabelRangeTlv, SrAlgoTlv, SrLocalBlockTlv, }; use crate::route::{SummaryNet, SummaryNetFlags, SummaryRtr}; use crate::version::Ospfv3; @@ -281,6 +281,12 @@ impl LsdbVersion for Ospfv3 { } } } + LsaOriginateEvent::HostnameChange => { + // (Re)originate Router-Info-LSA(s) in all areas. + for area in arenas.areas.iter() { + lsa_orig_router_info(area, instance); + } + } LsaOriginateEvent::BierEnableChange => { // Reoriginate Intra-area-prefix-LSA(s) in all areas. for area in arenas.areas.iter() { @@ -418,7 +424,7 @@ impl LsdbVersion for Ospfv3 { } fn lsdb_install( - instance: &InstanceUpView<'_, Self>, + instance: &mut InstanceUpView<'_, Self>, _arenas: &mut InstanceArenas, _lsdb_idx: LsdbIndex, lsdb_id: LsdbId, @@ -434,6 +440,22 @@ impl LsdbVersion for Ospfv3 { ); } } + + // Check for DynamicHostnameTlv + if lsa.hdr.lsa_type.function_code_normalized() + == Some(LsaFunctionCode::RouterInfo) + { + if let LsaBody::RouterInfo(router_info) = &lsa.body { + if let Some(hostname_tlv) = router_info.info_hostname.as_ref() { + instance + .state + .hostnames + .insert(lsa.hdr.adv_rtr, hostname_tlv.hostname.clone()); + } else { + instance.state.hostnames.remove(&lsa.hdr.adv_rtr); + } + } + } } } @@ -1074,6 +1096,11 @@ fn lsa_orig_router_info( srlb, msds: None, srms_pref: None, + info_hostname: instance + .shared + .hostname + .as_ref() + .map(|hostname| DynamicHostnameTlv::new(hostname.to_string())), unknown_tlvs: vec![], }); instance diff --git a/holo-ospf/src/ospfv3/packet/lsa.rs b/holo-ospf/src/ospfv3/packet/lsa.rs index 5e45a7e2..7d94b560 100644 --- a/holo-ospf/src/ospfv3/packet/lsa.rs +++ b/holo-ospf/src/ospfv3/packet/lsa.rs @@ -31,9 +31,10 @@ use crate::packet::lsa::{ }; use crate::packet::tlv::{ tlv_encode_end, tlv_encode_start, tlv_wire_len, AdjSidFlags, BierSubTlv, - GrReason, GrReasonTlv, GracePeriodTlv, MsdTlv, PrefixSidFlags, - RouterFuncCapsTlv, RouterInfoCapsTlv, RouterInfoTlvType, SidLabelRangeTlv, - SrAlgoTlv, SrLocalBlockTlv, SrmsPrefTlv, UnknownTlv, TLV_HDR_SIZE, + DynamicHostnameTlv, GrReason, GrReasonTlv, GracePeriodTlv, MsdTlv, + PrefixSidFlags, RouterFuncCapsTlv, RouterInfoCapsTlv, RouterInfoTlvType, + SidLabelRangeTlv, SrAlgoTlv, SrLocalBlockTlv, SrmsPrefTlv, UnknownTlv, + TLV_HDR_SIZE, }; use crate::version::Ospfv3; @@ -953,6 +954,9 @@ pub struct LsaRouterInfo { #[new(default)] pub srms_pref: Option, #[new(default)] + #[serde(skip)] + pub info_hostname: Option, + #[new(default)] pub unknown_tlvs: Vec, } @@ -2556,6 +2560,11 @@ impl LsaRouterInfo { RouterFuncCapsTlv::decode(tlv_len, &mut buf_tlv)?; router_info.func_caps.get_or_insert(caps); } + Some(RouterInfoTlvType::DynamicHostname) => { + let hostname = + DynamicHostnameTlv::decode(tlv_len, &mut buf_tlv)?; + router_info.info_hostname.get_or_insert(hostname); + } Some(RouterInfoTlvType::SrAlgo) => { let sr_algo = SrAlgoTlv::decode(tlv_len, &mut buf_tlv)?; router_info.sr_algo.get_or_insert(sr_algo); @@ -2596,6 +2605,9 @@ impl LsaRouterInfo { if let Some(func_caps) = &self.func_caps { func_caps.encode(buf); } + if let Some(info_hostname) = &self.info_hostname { + info_hostname.encode(buf); + } if let Some(sr_algo) = &self.sr_algo { sr_algo.encode(buf); } diff --git a/holo-ospf/src/packet/tlv.rs b/holo-ospf/src/packet/tlv.rs index cc70f1f1..ee209ee8 100644 --- a/holo-ospf/src/packet/tlv.rs +++ b/holo-ospf/src/packet/tlv.rs @@ -32,6 +32,7 @@ pub const TLV_HDR_SIZE: u16 = 4; pub enum RouterInfoTlvType { InformationalCaps = 1, FunctionalCaps = 2, + DynamicHostname = 7, SrAlgo = 8, SidLabelRange = 9, NodeMsd = 12, @@ -110,6 +111,27 @@ bitflags! { #[derive(Deserialize, Serialize)] pub struct RouterFuncCapsTlv(RouterFuncCaps); +// +// Dynamic Hostname TLV. +// +// Encoding format: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Type | Length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Hostname ... | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +#[derive(Clone, Debug, Default, Eq, new, PartialEq)] +#[derive(Deserialize, Serialize)] +pub struct DynamicHostnameTlv { + pub hostname: String, +} + +const MAX_HOSTNAME_LEN: usize = 255; + // // SR-Algorithm TLV. // @@ -534,6 +556,41 @@ impl From for RouterFuncCapsTlv { } } +// ===== impl DynamicHostnameTlv ==== + +impl DynamicHostnameTlv { + pub(crate) fn decode(tlv_len: u16, buf: &mut Bytes) -> DecodeResult { + if tlv_len == 0 { + return Err(DecodeError::InvalidTlvLength(tlv_len)); + } + + let mut hostname_bytes = [0; 255]; + buf.copy_to_slice( + &mut hostname_bytes + [..usize::min(tlv_len as usize, MAX_HOSTNAME_LEN)], + ); + + 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, RouterInfoTlvType::DynamicHostname); + let hostname = self.hostname.as_bytes(); + let hostname_len = usize::min(hostname.len(), MAX_HOSTNAME_LEN); + buf.put_slice(&hostname[..hostname_len]); + tlv_encode_end(buf, start_pos); + } + + pub(crate) fn get(&self) -> &str { + &self.hostname + } +} + // ===== impl SrAlgoTlv ===== impl SrAlgoTlv { diff --git a/holo-ospf/tests/packet/ospfv2.rs b/holo-ospf/tests/packet/ospfv2.rs index 53602b80..66e04674 100644 --- a/holo-ospf/tests/packet/ospfv2.rs +++ b/holo-ospf/tests/packet/ospfv2.rs @@ -570,12 +570,12 @@ static LSA2: Lazy<(Vec, Lsa)> = Lazy::new(|| { ( vec![ 0x00, 0x01, 0x42, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x80, 0x00, 0x00, 0x01, 0x20, 0x95, 0x00, 0x44, 0x00, 0x01, - 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x00, - 0x00, 0x01, 0x00, 0x03, 0x00, 0x3e, 0x80, 0x00, 0x00, 0x0e, 0x00, - 0x0b, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x3a, - 0x98, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x01, 0xb3, 0x3b, 0x00, 0x4c, 0x00, 0x01, + 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x68, + 0x6f, 0x6c, 0x6f, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x3e, 0x80, 0x00, 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x03, + 0xe8, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x3a, 0x98, 0x00, ], Lsa::new( 1, @@ -597,6 +597,7 @@ static LSA2: Lazy<(Vec, Lsa)> = Lazy::new(|| { )], msds: None, srms_pref: None, + info_hostname: Some(DynamicHostnameTlv::new("holo".to_owned())), unknown_tlvs: vec![], })), ), diff --git a/holo-ospf/tests/packet/ospfv3.rs b/holo-ospf/tests/packet/ospfv3.rs index 8f704a6d..ea4337ca 100644 --- a/holo-ospf/tests/packet/ospfv3.rs +++ b/holo-ospf/tests/packet/ospfv3.rs @@ -624,12 +624,12 @@ static LSA3: Lazy<(Vec, Lsa)> = Lazy::new(|| { ( vec![ 0x00, 0x01, 0xa0, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x80, 0x00, 0x00, 0x01, 0xf5, 0xa2, 0x00, 0x44, 0x00, 0x01, - 0x00, 0x04, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x00, - 0x00, 0x01, 0x00, 0x03, 0x00, 0x3e, 0x80, 0x00, 0x00, 0x0e, 0x00, - 0x0b, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x3a, - 0x98, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x01, 0x89, 0x48, 0x00, 0x4c, 0x00, 0x01, + 0x00, 0x04, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x68, + 0x6f, 0x6c, 0x6f, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x3e, 0x80, 0x00, 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x03, + 0xe8, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x3a, 0x98, 0x00, ], Lsa::new( 1, @@ -657,6 +657,7 @@ static LSA3: Lazy<(Vec, Lsa)> = Lazy::new(|| { )], msds: Default::default(), srms_pref: None, + info_hostname: Some(DynamicHostnameTlv::new("holo".to_owned())), unknown_tlvs: vec![], }), ), diff --git a/holo-yang/modules/augmentations/holo-ospf.yang b/holo-yang/modules/augmentations/holo-ospf.yang index d139bf15..1a8e2d7e 100644 --- a/holo-yang/modules/augmentations/holo-ospf.yang +++ b/holo-yang/modules/augmentations/holo-ospf.yang @@ -104,6 +104,36 @@ module holo-ospf { /* * Augmentations. */ + + augment "/rt:routing/rt:control-plane-protocols/" + + "rt:control-plane-protocol/ospf:ospf" { + container hostnames { + config false; + list hostname { + key "router-id"; + leaf router-id { + type rt-types:router-id; + description + "Router ID associated with the hostname."; + } + leaf hostname { + type string { + length "1..255"; + } + description + "Hostname associated with the router ID + as defined in RFC 5642."; + reference + "RFC 5642: Dynamic Hostname Exchange Mechanism for OSPF"; + } + description + "List of router ID / hostname associations."; + } + description + "Hostname-to-router-ID mapping database."; + } + } + augment "/rt:routing/rt:control-plane-protocols/" + "rt:control-plane-protocol/ospf:ospf" { when "derived-from-or-self(../rt:type, " diff --git a/holo-yang/modules/deviations/holo-ietf-ospf-deviations.yang b/holo-yang/modules/deviations/holo-ietf-ospf-deviations.yang index 78387dc6..18aee43f 100644 --- a/holo-yang/modules/deviations/holo-ietf-ospf-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-ospf-deviations.yang @@ -736,16 +736,6 @@ module holo-ietf-ospf-deviations { } */ - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:database/ospf:as-scope-lsa-type/ospf:as-scope-lsas/ospf:as-scope-lsa/ospf:version/ospf:ospfv2/ospf:ospfv2/ospf:body/ospf:opaque/ospf:ri-opaque/ospf:dynamic-hostname-tlv" { - deviate not-supported; - } - - /* - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:database/ospf:as-scope-lsa-type/ospf:as-scope-lsas/ospf:as-scope-lsa/ospf:version/ospf:ospfv2/ospf:ospfv2/ospf:body/ospf:opaque/ospf:ri-opaque/ospf:dynamic-hostname-tlv/ospf:hostname" { - deviate not-supported; - } - */ - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:database/ospf:as-scope-lsa-type/ospf:as-scope-lsas/ospf:as-scope-lsa/ospf:version/ospf:ospfv2/ospf:ospfv2/ospf:body/ospf:opaque/ospf:ri-opaque/ospf:sbfd-discriminator-tlv" { deviate not-supported; } @@ -950,16 +940,6 @@ module holo-ietf-ospf-deviations { } */ - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:database/ospf:as-scope-lsa-type/ospf:as-scope-lsas/ospf:as-scope-lsa/ospf:version/ospf:ospfv3/ospf:ospfv3/ospf:body/ospf:router-information/ospf:dynamic-hostname-tlv" { - deviate not-supported; - } - - /* - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:database/ospf:as-scope-lsa-type/ospf:as-scope-lsas/ospf:as-scope-lsa/ospf:version/ospf:ospfv3/ospf:ospfv3/ospf:body/ospf:router-information/ospf:dynamic-hostname-tlv/ospf:hostname" { - deviate not-supported; - } - */ - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:database/ospf:as-scope-lsa-type/ospf:as-scope-lsas/ospf:as-scope-lsa/ospf:version/ospf:ospfv3/ospf:ospfv3/ospf:body/ospf:router-information/ospf:sbfd-discriminator-tlv" { deviate not-supported; } @@ -1002,16 +982,6 @@ module holo-ietf-ospf-deviations { } */ - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:database/ospf:area-scope-lsa-type/ospf:area-scope-lsas/ospf:area-scope-lsa/ospf:version/ospf:ospfv2/ospf:ospfv2/ospf:body/ospf:opaque/ospf:ri-opaque/ospf:dynamic-hostname-tlv" { - deviate not-supported; - } - - /* - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:database/ospf:area-scope-lsa-type/ospf:area-scope-lsas/ospf:area-scope-lsa/ospf:version/ospf:ospfv2/ospf:ospfv2/ospf:body/ospf:opaque/ospf:ri-opaque/ospf:dynamic-hostname-tlv/ospf:hostname" { - deviate not-supported; - } - */ - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:database/ospf:area-scope-lsa-type/ospf:area-scope-lsas/ospf:area-scope-lsa/ospf:version/ospf:ospfv2/ospf:ospfv2/ospf:body/ospf:opaque/ospf:ri-opaque/ospf:sbfd-discriminator-tlv" { deviate not-supported; } @@ -1216,16 +1186,6 @@ module holo-ietf-ospf-deviations { } */ - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:database/ospf:area-scope-lsa-type/ospf:area-scope-lsas/ospf:area-scope-lsa/ospf:version/ospf:ospfv3/ospf:ospfv3/ospf:body/ospf:router-information/ospf:dynamic-hostname-tlv" { - deviate not-supported; - } - - /* - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:database/ospf:area-scope-lsa-type/ospf:area-scope-lsas/ospf:area-scope-lsa/ospf:version/ospf:ospfv3/ospf:ospfv3/ospf:body/ospf:router-information/ospf:dynamic-hostname-tlv/ospf:hostname" { - deviate not-supported; - } - */ - deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:database/ospf:area-scope-lsa-type/ospf:area-scope-lsas/ospf:area-scope-lsa/ospf:version/ospf:ospfv3/ospf:ospfv3/ospf:body/ospf:router-information/ospf:sbfd-discriminator-tlv" { deviate not-supported; } @@ -3191,4 +3151,4 @@ module holo-ietf-ospf-deviations { deviate not-supported; } */ -} +} \ No newline at end of file