Skip to content

Commit

Permalink
Merge pull request #41 from fliqqs/ospf-dynamic-hostname
Browse files Browse the repository at this point in the history
Ospf dynamic hostname
  • Loading branch information
rwestphal authored Jan 10, 2025
2 parents 37114c3 + fdadb83 commit 05b3b3f
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 68 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions holo-ospf/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1526,3 +1526,25 @@ where

Ok(())
}

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

pub(crate) fn process_hostname_update<V>(
instance: &mut Instance<V>,
hostname: Option<String>,
) -> Result<(), Error<V>>
where
V: Version,
{
instance.shared.hostname = hostname;

if let Some((instance, arenas)) = instance.as_up() {
V::lsa_orig_event(
&instance,
arenas,
LsaOriginateEvent::HostnameChange,
)?;
}

Ok(())
}
6 changes: 6 additions & 0 deletions holo-ospf/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ pub struct InstanceState<V: Version> {
pub gr_helper_count: usize,
// Authentication non-decreasing sequence number.
pub auth_seqno: Arc<AtomicU64>,
// Hostname cache.
pub hostnames: BTreeMap<Ipv4Addr, String>,
}

#[derive(Debug, Default)]
Expand Down Expand Up @@ -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(),
}
}
}
Expand Down Expand Up @@ -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.
_ => {}
}
Expand Down
3 changes: 2 additions & 1 deletion holo-ospf/src/lsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ pub enum LsaOriginateEvent {
BierCfgChange {
change: BierCfgEvent,
},
HostnameChange,
}

#[derive(Debug)]
Expand Down Expand Up @@ -211,7 +212,7 @@ pub trait LsdbVersion<V: Version> {

// Custom LSA installation handling.
fn lsdb_install(
instance: &InstanceUpView<'_, V>,
instance: &mut InstanceUpView<'_, V>,
arenas: &mut InstanceArenas<V>,
lsdb_idx: LsdbIndex,
lsdb_id: LsdbId,
Expand Down
73 changes: 73 additions & 0 deletions holo-ospf/src/northbound/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub enum ListEntry<'a, V: Version> {
LsaLog(&'a LsaLogEntry<V>),
Route(&'a V::IpNetwork, &'a RouteNet<V>),
Nexthop(&'a Nexthop<V::IpAddr>),
Hostname(&'a Ipv4Addr, &'a String),
AsStatsLsaType(&'a LsdbSingleType<V>),
AsLsaType(&'a LsdbSingleType<V>),
AsLsa(&'a LsaEntry<V>),
Expand Down Expand Up @@ -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()
}

Expand Down Expand Up @@ -662,6 +677,21 @@ fn load_callbacks_ospfv2() -> Callbacks<Instance<Ospfv2>> {
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<Ospfv2> = 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<Ospfv2> = args.parent_list_entry.as_as_lsa().unwrap();
Expand Down Expand Up @@ -1066,6 +1096,21 @@ fn load_callbacks_ospfv2() -> Callbacks<Instance<Ospfv2>> {
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<Ospfv2> = 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<Ospfv2> = args.parent_list_entry.as_area_lsa().unwrap();
Expand Down Expand Up @@ -1783,6 +1828,20 @@ fn load_callbacks_ospfv3() -> Callbacks<Instance<Ospfv3>> {
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<Ospfv3> = 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;
Expand Down Expand Up @@ -2250,6 +2309,20 @@ fn load_callbacks_ospfv3() -> Callbacks<Instance<Ospfv3>> {
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<Ospfv3> = 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;
Expand Down
33 changes: 30 additions & 3 deletions holo-ospf/src/ospfv2/lsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -240,6 +240,12 @@ impl LsdbVersion<Self> 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);
}
}
_ => (),
};

Expand Down Expand Up @@ -321,7 +327,7 @@ impl LsdbVersion<Self> for Ospfv2 {
}

fn lsdb_install(
instance: &InstanceUpView<'_, Self>,
instance: &mut InstanceUpView<'_, Self>,
arenas: &mut InstanceArenas<Self>,
lsdb_idx: LsdbIndex,
_lsdb_id: LsdbId,
Expand All @@ -346,6 +352,22 @@ impl LsdbVersion<Self> 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);
}
}
}
}

Expand Down Expand Up @@ -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(
Expand Down
18 changes: 14 additions & 4 deletions holo-ospf/src/ospfv2/packet/lsa_opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -122,6 +122,8 @@ pub struct LsaRouterInfo {
pub srlb: Vec<SrLocalBlockTlv>,
pub msds: Option<MsdTlv>,
pub srms_pref: Option<SrmsPrefTlv>,
#[serde(skip)]
pub info_hostname: Option<DynamicHostnameTlv>,
pub unknown_tlvs: Vec<UnknownTlv>,
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
35 changes: 31 additions & 4 deletions holo-ospf/src/ospfv3/lsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -281,6 +281,12 @@ impl LsdbVersion<Self> 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() {
Expand Down Expand Up @@ -418,7 +424,7 @@ impl LsdbVersion<Self> for Ospfv3 {
}

fn lsdb_install(
instance: &InstanceUpView<'_, Self>,
instance: &mut InstanceUpView<'_, Self>,
_arenas: &mut InstanceArenas<Self>,
_lsdb_idx: LsdbIndex,
lsdb_id: LsdbId,
Expand All @@ -434,6 +440,22 @@ impl LsdbVersion<Self> 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);
}
}
}
}
}

Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 05b3b3f

Please sign in to comment.