From 4f423da5a6e52437be1327e68cea7c2deceefda8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 27 Jun 2024 23:13:09 -0300 Subject: [PATCH 01/14] utils: introduce the `to_host_prefix` extension method for IP addresses Signed-off-by: Renato Westphal --- holo-routing/src/rib.rs | 12 +++--------- holo-utils/src/ip.rs | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/holo-routing/src/rib.rs b/holo-routing/src/rib.rs index ca5e29f7..6ae9e15a 100644 --- a/holo-routing/src/rib.rs +++ b/holo-routing/src/rib.rs @@ -11,9 +11,7 @@ use bitflags::bitflags; use chrono::{DateTime, Utc}; use derive_new::new; use holo_utils::ibus::IbusSender; -use holo_utils::ip::{ - AddressFamily, IpNetworkExt, Ipv4NetworkExt, Ipv6NetworkExt, -}; +use holo_utils::ip::{AddressFamily, IpNetworkExt, Ipv4AddrExt, Ipv6AddrExt}; use holo_utils::mpls::Label; use holo_utils::protocol::Protocol; use holo_utils::southbound::{ @@ -497,16 +495,12 @@ impl Rib { fn prefix_longest_match(&self, addr: &IpAddr) -> Option<&Route> { let lpm = match addr { IpAddr::V4(addr) => { - let prefix = - Ipv4Network::new(*addr, Ipv4Network::MAX_PREFIXLEN) - .unwrap(); + let prefix = addr.to_host_prefix(); let (_, lpm) = self.ipv4.get_lpm(&prefix)?; lpm } IpAddr::V6(addr) => { - let prefix = - Ipv6Network::new(*addr, Ipv6Network::MAX_PREFIXLEN) - .unwrap(); + let prefix = addr.to_host_prefix(); let (_, lpm) = self.ipv6.get_lpm(&prefix)?; lpm } diff --git a/holo-utils/src/ip.rs b/holo-utils/src/ip.rs index c3fabb62..c6a93bbd 100644 --- a/holo-utils/src/ip.rs +++ b/holo-utils/src/ip.rs @@ -38,6 +38,9 @@ pub trait IpAddrExt { // Returns true if this is an usable address. fn is_usable(&self) -> bool; + // Converts this IP address into a host prefix network. + fn to_host_prefix(&self) -> IpNetwork; + // Returns an unspecified address of the given address family. fn unspecified(af: AddressFamily) -> IpAddr; } @@ -48,6 +51,9 @@ pub trait Ipv4AddrExt { // Returns true if this is an usable address. fn is_usable(&self) -> bool; + + // Converts this IPv4 address into a host prefix network. + fn to_host_prefix(&self) -> Ipv4Network; } // Extension methods for Ipv6Addr. @@ -56,6 +62,9 @@ pub trait Ipv6AddrExt { // Returns true if this is an usable address. fn is_usable(&self) -> bool; + + // Converts this IPv6 address into a host prefix network. + fn to_host_prefix(&self) -> Ipv6Network; } // Extension methods for IpNetwork. @@ -238,6 +247,13 @@ impl IpAddrExt for IpAddr { !(self.is_loopback() || self.is_multicast() || self.is_unspecified()) } + fn to_host_prefix(&self) -> IpNetwork { + match self { + IpAddr::V4(addr) => addr.to_host_prefix().into(), + IpAddr::V6(addr) => addr.to_host_prefix().into(), + } + } + fn unspecified(af: AddressFamily) -> IpAddr { match af { AddressFamily::Ipv4 => IpAddr::V4(Ipv4Addr::UNSPECIFIED), @@ -274,6 +290,10 @@ impl Ipv4AddrExt for Ipv4Addr { || self.is_multicast() || self.is_unspecified()) } + + fn to_host_prefix(&self) -> Ipv4Network { + Ipv4Network::new(*self, Ipv4Network::MAX_PREFIXLEN).unwrap() + } } impl IpAddrKind for Ipv4Addr { @@ -301,6 +321,10 @@ impl Ipv6AddrExt for Ipv6Addr { fn is_usable(&self) -> bool { !(self.is_loopback() || self.is_multicast() || self.is_unspecified()) } + + fn to_host_prefix(&self) -> Ipv6Network { + Ipv6Network::new(*self, Ipv6Network::MAX_PREFIXLEN).unwrap() + } } impl IpAddrKind for Ipv6Addr { From 2ea4e07bf7462548f291fe509ee6152cb97ff405 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 27 Jun 2024 23:33:56 -0300 Subject: [PATCH 02/14] ospf: update to ietf-ospf-sr-mpls@2024-06-19.yang Signed-off-by: Renato Westphal --- holo-ospf/src/northbound/state.rs | 90 +++++++++---------- ...yang => ietf-ospf-sr-mpls@2024-06-19.yang} | 23 +++-- holo-yang/src/lib.rs | 4 +- 3 files changed, 59 insertions(+), 58 deletions(-) rename holo-yang/modules/ietf/{ietf-ospf-sr-mpls@2024-01-18.yang => ietf-ospf-sr-mpls@2024-06-19.yang} (98%) diff --git a/holo-ospf/src/northbound/state.rs b/holo-ospf/src/northbound/state.rs index 09c133a1..58f0e374 100644 --- a/holo-ospf/src/northbound/state.rs +++ b/holo-ospf/src/northbound/state.rs @@ -5,6 +5,7 @@ // use std::borrow::Cow; +use std::collections::BTreeMap; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::sync::LazyLock as Lazy; use std::time::Instant; @@ -18,6 +19,7 @@ use holo_utils::ip::IpAddrKind; use holo_utils::num::SaturatingInto; use holo_utils::option::OptionExt; use holo_utils::protocol::Protocol; +use holo_utils::sr::IgpAlgoType; use holo_yang::{ToYang, ToYangBits}; use num_traits::FromPrimitive; @@ -75,8 +77,10 @@ pub enum ListEntry<'a, V: Version> { // OSPFv3 Ospfv3RouterLsaLink(&'a ospfv3::packet::lsa::LsaRouterLink), Ospfv3LinkLsaPrefix(&'a ospfv3::packet::lsa::LsaLinkPrefix), + Ospfv3AdjSids(&'a Vec), Ospfv3AdjSid(&'a ospfv3::packet::lsa::AdjSid), Ospfv3IntraAreaLsaPrefix(&'a ospfv3::packet::lsa::LsaIntraAreaPrefixEntry), + Ospfv3PrefixSids(&'a BTreeMap), Ospfv3PrefixSid(&'a ospfv3::packet::lsa::PrefixSid), Ospfv3LinkLocalAddr(IpAddr), } @@ -1958,28 +1962,23 @@ fn load_callbacks_ospfv3() -> Callbacks> { value: Some(tlv.value.as_ref()), }) }) - .path(ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::e_as_external::e_external_tlvs::external_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PATH) + .path(ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::e_as_external::e_external_tlvs::external_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PATH) .get_iterate(|_instance, args| { - let lse: &LsaEntry = args.parent_list_entry.as_as_lsa().unwrap(); - let lsa = &lse.data; - if let Some(lsa_body) = lsa.body.as_ext_as_external() { - let iter = lsa_body.prefix_sids.values().map(ListEntry::Ospfv3PrefixSid); - Some(Box::new(iter)) - } else { - None - } + let prefix_sids = args.parent_list_entry.as_ospfv3_prefix_sids()?; + let iter = prefix_sids.values().map(ListEntry::Ospfv3PrefixSid); + Some(Box::new(iter)) }) .get_object(|_instance, args| { - use ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::e_as_external::e_external_tlvs::external_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PrefixSidSubTlv; + use ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::e_as_external::e_external_tlvs::external_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PrefixSidSubTlv; let prefix_sid = args.list_entry.as_ospfv3_prefix_sid().unwrap(); Box::new(PrefixSidSubTlv { algorithm: Some(prefix_sid.algo.to_yang()), sid: Some(prefix_sid.sid.value()), }) }) - .path(ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::e_as_external::e_external_tlvs::external_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::PATH) + .path(ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::e_as_external::e_external_tlvs::external_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::PATH) .get_object(|_instance, args| { - use ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::e_as_external::e_external_tlvs::external_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::Ospfv3PrefixSidFlags; + use ospf::database::as_scope_lsa_type::as_scope_lsas::as_scope_lsa::ospfv3::body::e_as_external::e_external_tlvs::external_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::Ospfv3PrefixSidFlags; let prefix_sid = args.list_entry.as_ospfv3_prefix_sid().unwrap(); let iter = prefix_sid.flags.to_yang_bits().into_iter().map(Cow::Borrowed); Box::new(Ospfv3PrefixSidFlags { @@ -2390,7 +2389,7 @@ fn load_callbacks_ospfv3() -> Callbacks> { .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::PATH) .get_iterate(|_instance, args| { let tlv = args.parent_list_entry.as_ospfv3_router_lsa_link().unwrap(); - let iter = tlv.unknown_stlvs.iter().map(ListEntry::UnknownTlv); + let iter = tlv.unknown_stlvs.iter().map(ListEntry::UnknownTlv).chain(std::iter::once(ListEntry::Ospfv3AdjSids(&tlv.adj_sids))); Some(Box::new(iter)) }) .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::unknown_sub_tlv::PATH) @@ -2403,37 +2402,37 @@ fn load_callbacks_ospfv3() -> Callbacks> { value: Some(tlv.value.as_ref()), }) }) - .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::adj_sid_sub_tlvs::adj_sid_sub_tlv::PATH) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::adj_sid_sub_tlvs::adj_sid_sub_tlv::PATH) .get_iterate(|_instance, args| { - let rtr_link = args.parent_list_entry.as_ospfv3_router_lsa_link().unwrap(); - let iter = rtr_link.adj_sids.iter().filter(|adj_sid| adj_sid.nbr_router_id.is_none()).map(ListEntry::Ospfv3AdjSid); + let adj_sids = args.parent_list_entry.as_ospfv3_adj_sids()?; + let iter = adj_sids.iter().filter(|adj_sid| adj_sid.nbr_router_id.is_none()).map(ListEntry::Ospfv3AdjSid); Some(Box::new(iter)) }) .get_object(|_instance, args| { - use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::adj_sid_sub_tlvs::adj_sid_sub_tlv::AdjSidSubTlv; + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::adj_sid_sub_tlvs::adj_sid_sub_tlv::AdjSidSubTlv; let adj_sid = args.list_entry.as_ospfv3_adj_sid().unwrap(); Box::new(AdjSidSubTlv { weight: Some(adj_sid.weight), sid: Some(adj_sid.sid.value()), }) }) - .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::adj_sid_sub_tlvs::adj_sid_sub_tlv::adj_sid_flags::PATH) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::adj_sid_sub_tlvs::adj_sid_sub_tlv::adj_sid_flags::PATH) .get_object(|_instance, args| { - use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::adj_sid_sub_tlvs::adj_sid_sub_tlv::adj_sid_flags::AdjSidFlags; + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::adj_sid_sub_tlvs::adj_sid_sub_tlv::adj_sid_flags::AdjSidFlags; let adj_sid = args.list_entry.as_ospfv3_adj_sid().unwrap(); let iter = adj_sid.flags.to_yang_bits().into_iter().map(Cow::Borrowed); Box::new(AdjSidFlags { flags: Some(Box::new(iter)), }) }) - .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::lan_adj_sid_sub_tlvs::lan_adj_sid_sub_tlv::PATH) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::lan_adj_sid_sub_tlvs::lan_adj_sid_sub_tlv::PATH) .get_iterate(|_instance, args| { - let rtr_link = args.parent_list_entry.as_ospfv3_router_lsa_link().unwrap(); - let iter = rtr_link.adj_sids.iter().filter(|adj_sid| adj_sid.nbr_router_id.is_some()).map(ListEntry::Ospfv3AdjSid); + let adj_sids = args.parent_list_entry.as_ospfv3_adj_sids()?; + let iter = adj_sids.iter().filter(|adj_sid| adj_sid.nbr_router_id.is_some()).map(ListEntry::Ospfv3AdjSid); Some(Box::new(iter)) }) .get_object(|_instance, args| { - use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::lan_adj_sid_sub_tlvs::lan_adj_sid_sub_tlv::LanAdjSidSubTlv; + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::lan_adj_sid_sub_tlvs::lan_adj_sid_sub_tlv::LanAdjSidSubTlv; let adj_sid = args.list_entry.as_ospfv3_adj_sid().unwrap(); Box::new(LanAdjSidSubTlv { weight: Some(adj_sid.weight), @@ -2441,9 +2440,9 @@ fn load_callbacks_ospfv3() -> Callbacks> { sid: Some(adj_sid.sid.value()), }) }) - .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::lan_adj_sid_sub_tlvs::lan_adj_sid_sub_tlv::lan_adj_sid_flags::PATH) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::lan_adj_sid_sub_tlvs::lan_adj_sid_sub_tlv::lan_adj_sid_flags::PATH) .get_object(|_instance, args| { - use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::lan_adj_sid_sub_tlvs::lan_adj_sid_sub_tlv::lan_adj_sid_flags::LanAdjSidFlags; + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_router::e_router_tlvs::link_tlv::sub_tlvs::lan_adj_sid_sub_tlvs::lan_adj_sid_sub_tlv::lan_adj_sid_flags::LanAdjSidFlags; let adj_sid = args.list_entry.as_ospfv3_adj_sid().unwrap(); let iter = adj_sid.flags.to_yang_bits().into_iter().map(Cow::Borrowed); Box::new(LanAdjSidFlags { @@ -2548,8 +2547,8 @@ fn load_callbacks_ospfv3() -> Callbacks> { .get_iterate(|_instance, args| { let lse: &LsaEntry = args.parent_list_entry.as_area_lsa().unwrap(); let lsa = &lse.data; - if let Some(lsa_body) = lsa.body.as_ext_inter_area_router() { - let iter = lsa_body.unknown_stlvs.iter().map(ListEntry::UnknownTlv); + if let Some(lsa_body) = lsa.body.as_ext_inter_area_prefix() { + let iter = lsa_body.unknown_stlvs.iter().map(ListEntry::UnknownTlv).chain(std::iter::once(ListEntry::Ospfv3PrefixSids(&lsa_body.prefix_sids))); Some(Box::new(iter)) } else { None @@ -2565,28 +2564,23 @@ fn load_callbacks_ospfv3() -> Callbacks> { value: Some(tlv.value.as_ref()), }) }) - .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_inter_area_prefix::e_inter_prefix_tlvs::inter_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PATH) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_inter_area_prefix::e_inter_prefix_tlvs::inter_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PATH) .get_iterate(|_instance, args| { - let lse: &LsaEntry = args.parent_list_entry.as_area_lsa().unwrap(); - let lsa = &lse.data; - if let Some(lsa_body) = lsa.body.as_ext_inter_area_prefix() { - let iter = lsa_body.prefix_sids.values().map(ListEntry::Ospfv3PrefixSid); - Some(Box::new(iter)) - } else { - None - } + let prefix_sids = args.parent_list_entry.as_ospfv3_prefix_sids()?; + let iter = prefix_sids.values().map(ListEntry::Ospfv3PrefixSid); + Some(Box::new(iter)) }) .get_object(|_instance, args| { - use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_inter_area_prefix::e_inter_prefix_tlvs::inter_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PrefixSidSubTlv; + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_inter_area_prefix::e_inter_prefix_tlvs::inter_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PrefixSidSubTlv; let prefix_sid = args.list_entry.as_ospfv3_prefix_sid().unwrap(); Box::new(PrefixSidSubTlv { algorithm: Some(prefix_sid.algo.to_yang()), sid: Some(prefix_sid.sid.value()), }) }) - .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_inter_area_prefix::e_inter_prefix_tlvs::inter_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::PATH) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_inter_area_prefix::e_inter_prefix_tlvs::inter_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::PATH) .get_object(|_instance, args| { - use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_inter_area_prefix::e_inter_prefix_tlvs::inter_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::Ospfv3PrefixSidFlags; + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_inter_area_prefix::e_inter_prefix_tlvs::inter_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::Ospfv3PrefixSidFlags; let prefix_sid = args.list_entry.as_ospfv3_prefix_sid().unwrap(); let iter = prefix_sid.flags.to_yang_bits().into_iter().map(Cow::Borrowed); Box::new(Ospfv3PrefixSidFlags { @@ -2726,7 +2720,7 @@ fn load_callbacks_ospfv3() -> Callbacks> { .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::sub_tlvs::PATH) .get_iterate(|_instance, args| { let prefix = args.parent_list_entry.as_ospfv3_intra_area_lsa_prefix().unwrap(); - let iter = prefix.unknown_stlvs.iter().map(ListEntry::UnknownTlv); + let iter = prefix.unknown_stlvs.iter().map(ListEntry::UnknownTlv).chain(std::iter::once(ListEntry::Ospfv3PrefixSids(&prefix.prefix_sids))); Some(Box::new(iter)) }) .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::sub_tlvs::unknown_sub_tlv::PATH) @@ -2739,23 +2733,23 @@ fn load_callbacks_ospfv3() -> Callbacks> { value: Some(tlv.value.as_ref()), }) }) - .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PATH) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PATH) .get_iterate(|_instance, args| { - let prefix = args.parent_list_entry.as_ospfv3_intra_area_lsa_prefix().unwrap(); - let iter = prefix.prefix_sids.values().map(ListEntry::Ospfv3PrefixSid); + let prefix_sids = args.parent_list_entry.as_ospfv3_prefix_sids()?; + let iter = prefix_sids.values().map(ListEntry::Ospfv3PrefixSid); Some(Box::new(iter)) }) .get_object(|_instance, args| { - use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PrefixSidSubTlv; + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PrefixSidSubTlv; let prefix_sid = args.list_entry.as_ospfv3_prefix_sid().unwrap(); Box::new(PrefixSidSubTlv { algorithm: Some(prefix_sid.algo.to_yang()), sid: Some(prefix_sid.sid.value()), }) }) - .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::PATH) + .path(ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::PATH) .get_object(|_instance, args| { - use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::Ospfv3PrefixSidFlags; + use ospf::areas::area::database::area_scope_lsa_type::area_scope_lsas::area_scope_lsa::ospfv3::body::e_intra_area_prefix::e_intra_prefix_tlvs::intra_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::Ospfv3PrefixSidFlags; let prefix_sid = args.list_entry.as_ospfv3_prefix_sid().unwrap(); let iter = prefix_sid.flags.to_yang_bits().into_iter().map(Cow::Borrowed); Box::new(Ospfv3PrefixSidFlags { @@ -3082,10 +3076,10 @@ fn load_callbacks_ospfv3() -> Callbacks> { value: Some(tlv.value.as_ref()), }) }) - .path(ospf::areas::area::interfaces::interface::database::link_scope_lsa_type::link_scope_lsas::link_scope_lsa::ospfv3::body::e_link::e_link_tlvs::intra_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PATH) + .path(ospf::areas::area::interfaces::interface::database::link_scope_lsa_type::link_scope_lsas::link_scope_lsa::ospfv3::body::e_link::e_link_tlvs::intra_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::PATH) .get_iterate(|_instance, _args| None) .get_object(|_instance, _args| unreachable!()) - .path(ospf::areas::area::interfaces::interface::database::link_scope_lsa_type::link_scope_lsas::link_scope_lsa::ospfv3::body::e_link::e_link_tlvs::intra_prefix_tlv::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::PATH) + .path(ospf::areas::area::interfaces::interface::database::link_scope_lsa_type::link_scope_lsas::link_scope_lsa::ospfv3::body::e_link::e_link_tlvs::intra_prefix_tlv::sub_tlvs::prefix_sid_sub_tlvs::prefix_sid_sub_tlv::ospfv3_prefix_sid_flags::PATH) .get_object(|_instance, _args| unreachable!()) .path(ospf::areas::area::interfaces::interface::database::link_scope_lsa_type::link_scope_lsas::link_scope_lsa::ospfv3::body::e_link::e_link_tlvs::ipv6_link_local_addr_tlv::PATH) .get_object(|_instance, args| { diff --git a/holo-yang/modules/ietf/ietf-ospf-sr-mpls@2024-01-18.yang b/holo-yang/modules/ietf/ietf-ospf-sr-mpls@2024-06-19.yang similarity index 98% rename from holo-yang/modules/ietf/ietf-ospf-sr-mpls@2024-01-18.yang rename to holo-yang/modules/ietf/ietf-ospf-sr-mpls@2024-06-19.yang index 140baecb..bbd5bc2e 100644 --- a/holo-yang/modules/ietf/ietf-ospf-sr-mpls@2024-01-18.yang +++ b/holo-yang/modules/ietf/ietf-ospf-sr-mpls@2024-06-19.yang @@ -42,7 +42,7 @@ module ietf-ospf-sr-mpls { import ietf-ospfv3-extended-lsa { prefix ospfv3-e-lsa; reference - "RFC XXXX - YANG Data Model for OSPFv3 Extended LSAs"; + "RFC 9587 - YANG Data Model for OSPFv3 Extended LSAs"; } organization @@ -97,7 +97,7 @@ module ietf-ospf-sr-mpls { reference "RFC XXXX"; - revision 2024-01-18 { + revision 2024-06-19 { description "Initial revision."; reference @@ -1203,7 +1203,8 @@ module ietf-ospf-sr-mpls { + "ospf:link-scope-lsas/ospf:link-scope-lsa/" + "ospf:version/ospf:ospfv3/ospf:ospfv3/" + "ospf:body/ospfv3-e-lsa:e-link/" - + "ospfv3-e-lsa:e-link-tlvs/ospfv3-e-lsa:intra-prefix-tlv" { + + "ospfv3-e-lsa:e-link-tlvs/ospfv3-e-lsa:intra-prefix-tlv/" + + "ospfv3-e-lsa:sub-tlvs" { when "derived-from(/rt:routing/rt:control-plane-protocols/" + "rt:control-plane-protocol/rt:type, 'ospf:ospfv3')" { description @@ -1222,7 +1223,8 @@ module ietf-ospf-sr-mpls { + "ospf:area-scope-lsa/ospf:version/ospf:ospfv3/" + "ospf:ospfv3/ospf:body/ospfv3-e-lsa:e-intra-area-prefix/" + "ospfv3-e-lsa:e-intra-prefix-tlvs/" - + "ospfv3-e-lsa:intra-prefix-tlv" { + + "ospfv3-e-lsa:intra-prefix-tlv/" + + "ospfv3-e-lsa:sub-tlvs" { when "derived-from(/rt:routing/rt:control-plane-protocols/" + "rt:control-plane-protocol/rt:type, 'ospf:ospfv3')" { description @@ -1243,7 +1245,8 @@ module ietf-ospf-sr-mpls { + "ospf:area-scope-lsa/ospf:version/ospf:ospfv3/" + "ospf:ospfv3/ospf:body/ospfv3-e-lsa:e-inter-area-prefix/" + "ospfv3-e-lsa:e-inter-prefix-tlvs/" - + "ospfv3-e-lsa:inter-prefix-tlv" { + + "ospfv3-e-lsa:inter-prefix-tlv/" + + "ospfv3-e-lsa:sub-tlvs" { when "derived-from(/rt:routing/rt:control-plane-protocols/" + "rt:control-plane-protocol/rt:type, 'ospf:ospfv3')" { description @@ -1264,7 +1267,8 @@ module ietf-ospf-sr-mpls { + "ospf:as-scope-lsa/ospf:version/ospf:ospfv3/" + "ospf:ospfv3/ospf:body/ospfv3-e-lsa:e-as-external/" + "ospfv3-e-lsa:e-external-tlvs/" - + "ospfv3-e-lsa:external-prefix-tlv" { + + "ospfv3-e-lsa:external-prefix-tlv/" + + "ospfv3-e-lsa:sub-tlvs" { when "derived-from(/rt:routing/rt:control-plane-protocols/" + "rt:control-plane-protocol/rt:type, 'ospf:ospfv3')" { description @@ -1282,7 +1286,8 @@ module ietf-ospf-sr-mpls { + "ospf:area-scope-lsa/ospf:version/ospf:ospfv3/" + "ospf:ospfv3/ospf:body/ospfv3-e-lsa:e-nssa/" + "ospfv3-e-lsa:e-external-tlvs/" - + "ospfv3-e-lsa:external-prefix-tlv" { + + "ospfv3-e-lsa:external-prefix-tlv/" + + "ospfv3-e-lsa:sub-tlvs" { when "derived-from(/rt:routing/rt:control-plane-protocols/" + "rt:control-plane-protocol/rt:type, 'ospf:ospfv3')" { description @@ -1292,6 +1297,7 @@ module ietf-ospf-sr-mpls { description "OSPFv3 Area-Scoped External Prefix TLV."; } + /* Adj-SID sub-TLV */ augment "/rt:routing/" @@ -1300,7 +1306,8 @@ module ietf-ospf-sr-mpls { + "ospf:area-scope-lsa-type/ospf:area-scope-lsas/" + "ospf:area-scope-lsa/ospf:version/ospf:ospfv3/" + "ospf:ospfv3/ospf:body/ospfv3-e-lsa:e-router/" - + "ospfv3-e-lsa:e-router-tlvs/ospfv3-e-lsa:link-tlv" { + + "ospfv3-e-lsa:e-router-tlvs/ospfv3-e-lsa:link-tlv/" + + "ospfv3-e-lsa:sub-tlvs" { when "derived-from(/rt:routing/rt:control-plane-protocols/" + "rt:control-plane-protocol/rt:type, 'ospf:ospfv3')" { description diff --git a/holo-yang/src/lib.rs b/holo-yang/src/lib.rs index 693ba4ef..e21e1338 100644 --- a/holo-yang/src/lib.rs +++ b/holo-yang/src/lib.rs @@ -97,8 +97,8 @@ pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { include_str!("../modules/ietf/ietf-netconf-acm@2018-02-14.yang"), EmbeddedModuleKey::new("ietf-ospf", Some("2022-10-19"), None, None) => include_str!("../modules/ietf/ietf-ospf@2022-10-19.yang"), - EmbeddedModuleKey::new("ietf-ospf-sr-mpls", Some("2024-01-18"), None, None) => - include_str!("../modules/ietf/ietf-ospf-sr-mpls@2024-01-18.yang"), + EmbeddedModuleKey::new("ietf-ospf-sr-mpls", Some("2024-06-19"), None, None) => + include_str!("../modules/ietf/ietf-ospf-sr-mpls@2024-06-19.yang"), EmbeddedModuleKey::new("ietf-ospfv3-extended-lsa", Some("2024-06-07"), None, None) => include_str!("../modules/ietf/ietf-ospfv3-extended-lsa@2024-06-07.yang"), EmbeddedModuleKey::new("ietf-rip", Some("2020-02-20"), None, None) => From 795340da937fd0ccb44c74614f53d9cc8776ebf7 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 2 Jul 2024 21:24:20 -0300 Subject: [PATCH 03/14] daemon: improve configuration data fetching to support XPath expressions Signed-off-by: Renato Westphal --- holo-daemon/src/northbound/core.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/holo-daemon/src/northbound/core.rs b/holo-daemon/src/northbound/core.rs index bb0a7342..23c8546c 100644 --- a/holo-daemon/src/northbound/core.rs +++ b/holo-daemon/src/northbound/core.rs @@ -516,12 +516,20 @@ impl Northbound { // Gets a full or partial copy of the running configuration. fn get_configuration(&self, path: Option<&str>) -> Result { match path { - Some(path) => self - .running_config - .find_path(path) - .map_err(Error::YangInvalidPath)? - .duplicate(true) - .map_err(Error::YangInternal), + Some(path) => { + let yang_ctx = YANG_CTX.get().unwrap(); + let mut dtree = DataTree::new(yang_ctx); + for dnode in self + .running_config + .find_xpath(path) + .map_err(Error::YangInvalidPath)? + { + let subtree = + dnode.duplicate(true).map_err(Error::YangInternal)?; + dtree.merge(&subtree).map_err(Error::YangInternal)?; + } + Ok(dtree) + } None => { self.running_config.duplicate().map_err(Error::YangInternal) } From bbeaa7eecc55061da79f58dff71d83da360d18da Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 2 Jul 2024 21:24:56 -0300 Subject: [PATCH 04/14] grpc: add `with_defaults` parameter to the `Get` RPC Signed-off-by: Renato Westphal --- holo-daemon/src/northbound/client/grpc.rs | 10 ++++++---- proto/holo.proto | 5 ++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/holo-daemon/src/northbound/client/grpc.rs b/holo-daemon/src/northbound/client/grpc.rs index 2712a774..d67b6fee 100644 --- a/holo-daemon/src/northbound/client/grpc.rs +++ b/holo-daemon/src/northbound/client/grpc.rs @@ -98,6 +98,7 @@ impl proto::Northbound for NorthboundService { let data_type = api::DataType::try_from(grpc_request.r#type)?; let encoding = proto::Encoding::try_from(grpc_request.encoding) .map_err(|_| Status::invalid_argument("Invalid data encoding"))?; + let with_defaults = grpc_request.with_defaults; let path = (!grpc_request.path.is_empty()).then_some(grpc_request.path); let nb_request = api::client::Request::Get(api::client::GetRequest { data_type, @@ -110,12 +111,13 @@ impl proto::Northbound for NorthboundService { let nb_response = responder_rx.await.unwrap()?; // Convert and relay northbound response to the gRPC client. + let mut printer_flags = DataPrinterFlags::WITH_SIBLINGS; + if with_defaults { + printer_flags.insert(DataPrinterFlags::WD_ALL); + } let data = nb_response .dtree - .print_string( - DataFormat::from(encoding), - DataPrinterFlags::WITH_SIBLINGS, - ) + .print_string(DataFormat::from(encoding), printer_flags) .map_err(|error| Status::internal(error.to_string()))? .unwrap_or_default(); let grpc_response = proto::GetResponse { diff --git a/proto/holo.proto b/proto/holo.proto index 1aa0768a..61675e21 100644 --- a/proto/holo.proto +++ b/proto/holo.proto @@ -93,8 +93,11 @@ message GetRequest { // Encoding to be used. Encoding encoding = 2; + // Include implicit default nodes. + bool with_defaults = 3; + // Requested YANG path. - string path = 3; + string path = 4; } message GetResponse { From 7f185722d63c08fd20845c4aaa9138b57e4f1814 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 5 Jul 2024 18:30:26 -0300 Subject: [PATCH 05/14] build: remove unused feature from prefix-trie dependency The "ipnet" feature is enabled by default and pulls in an additional dependency, but we don't need it. Disable it to reduce dependency footprint. Signed-off-by: Renato Westphal --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e500401f..9323d9a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ netlink-sys = "0.8" num-derive = "0.4" num-traits = "0.2" pickledb = "0.5" -prefix-trie = { version = "0.4.1", features = ["ipnetwork"] } +prefix-trie = { version = "0.4.1", default-features = false, features = ["ipnetwork"] } prost = "0.12" rand = "0.8.5" regex = "1.10" From 01c851695dd91b712d8fd0b2f6226fab6bbf6fbc Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 5 Jul 2024 19:38:59 -0300 Subject: [PATCH 06/14] build: adopt new "dep:" syntax for specifying feature dependencies Signed-off-by: Renato Westphal --- holo-daemon/Cargo.toml | 20 ++++++++++---------- holo-routing/Cargo.toml | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/holo-daemon/Cargo.toml b/holo-daemon/Cargo.toml index 3990ec98..c7f0f5e7 100644 --- a/holo-daemon/Cargo.toml +++ b/holo-daemon/Cargo.toml @@ -70,17 +70,17 @@ default = [ ] # Base components -interface = ["holo-interface"] -keychain = ["holo-keychain"] -policy = ["holo-policy", "holo-routing"] -routing = ["holo-routing", "holo-interface"] +interface = ["dep:holo-interface"] +keychain = ["dep:holo-keychain"] +policy = ["dep:holo-policy", "dep:holo-routing"] +routing = ["dep:holo-routing", "dep:holo-interface"] # Protocols -bfd = ["holo-bfd", "holo-routing/bfd"] -bgp = ["holo-bgp", "holo-routing/bgp"] -ldp = ["holo-ldp", "holo-routing/ldp"] -ospf = ["holo-ospf", "holo-routing/ospf"] -rip = ["holo-rip", "holo-routing/rip"] +bfd = ["dep:holo-bfd", "holo-routing/bfd"] +bgp = ["dep:holo-bgp", "holo-routing/bgp"] +ldp = ["dep:holo-ldp", "holo-routing/ldp"] +ospf = ["dep:holo-ospf", "holo-routing/ospf"] +rip = ["dep:holo-rip", "holo-routing/rip"] # Other features -io_uring = ["tokio-uring"] +io_uring = ["dep:tokio-uring"] diff --git a/holo-routing/Cargo.toml b/holo-routing/Cargo.toml index 39d1ae5b..7b560c1f 100644 --- a/holo-routing/Cargo.toml +++ b/holo-routing/Cargo.toml @@ -36,8 +36,8 @@ holo-rip = { path = "../holo-rip", optional = true } workspace = true [features] -bfd = ["holo-bfd"] -bgp = ["holo-bgp"] -ldp = ["holo-ldp"] -ospf = ["holo-ospf"] -rip = ["holo-rip"] +bfd = ["dep:holo-bfd"] +bgp = ["dep:holo-bgp"] +ldp = ["dep:holo-ldp"] +ospf = ["dep:holo-ospf"] +rip = ["dep:holo-rip"] From 51cf126da64355f2e15d02f73aa7d9b4417b1b3a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 5 Jul 2024 20:55:31 -0300 Subject: [PATCH 07/14] daemon: make tokio-console integration an optional feature The tokio-console integration is excellent for debugging but shouldn't be needed by regular users. Using cargo-tree, it's possible to see that the console-subscriber crate pulls in several additional dependencies, which impact the final binary size and build time as well. As such, make tokio-console integration optional so that this cost is incurred only when necessary. Signed-off-by: Renato Westphal --- holo-daemon/Cargo.toml | 3 ++- holo-daemon/holod.toml | 5 ---- holo-daemon/src/config.rs | 8 ------ holo-daemon/src/main.rs | 57 ++++++++++++++++++++++----------------- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/holo-daemon/Cargo.toml b/holo-daemon/Cargo.toml index c7f0f5e7..43a42c3d 100644 --- a/holo-daemon/Cargo.toml +++ b/holo-daemon/Cargo.toml @@ -6,7 +6,7 @@ license.workspace = true edition.workspace = true [dependencies] -console-subscriber = "0.3" +console-subscriber = { version = "0.3", optional = true } prost-types = "0.12" toml = "0.5" tokio-uring = { version = "0.5", optional = true } @@ -83,4 +83,5 @@ ospf = ["dep:holo-ospf", "holo-routing/ospf"] rip = ["dep:holo-rip", "holo-routing/rip"] # Other features +tokio_console = ["dep:console-subscriber"] io_uring = ["dep:tokio-uring"] diff --git a/holo-daemon/holod.toml b/holo-daemon/holod.toml index b2cf1ae0..7a6c229a 100644 --- a/holo-daemon/holod.toml +++ b/holo-daemon/holod.toml @@ -47,11 +47,6 @@ database_path = "/var/run/holo/holo.db" # Sets whether or not an event’s source code file path and line number are displayed show_source = false -# Instrumentation using tokio-console (a diagnostics and debugging tool) -[tokio_console] - # Enable or disable - enabled = false - # Event recorder (useful for bug reporting) [event_recorder] # Enable or disable the event recorder diff --git a/holo-daemon/src/config.rs b/holo-daemon/src/config.rs index df9c6726..386f8966 100644 --- a/holo-daemon/src/config.rs +++ b/holo-daemon/src/config.rs @@ -16,7 +16,6 @@ pub struct Config { pub group: String, pub database_path: String, pub logging: Logging, - pub tokio_console: TokioConsole, pub event_recorder: event_recorder::Config, pub plugins: Plugins, } @@ -73,12 +72,6 @@ pub enum LoggingFmtStyle { Pretty, } -#[derive(Debug, Default, Deserialize)] -#[serde(default, deny_unknown_fields)] -pub struct TokioConsole { - pub enabled: bool, -} - #[derive(Debug, Default, Deserialize)] #[serde(default, deny_unknown_fields)] pub struct Plugins { @@ -139,7 +132,6 @@ impl Default for Config { group: "holo".to_owned(), database_path: "/var/run/holo/holo.db".to_owned(), logging: Default::default(), - tokio_console: Default::default(), event_recorder: Default::default(), plugins: Default::default(), } diff --git a/holo-daemon/src/main.rs b/holo-daemon/src/main.rs index e874a1a9..76ebacd1 100644 --- a/holo-daemon/src/main.rs +++ b/holo-daemon/src/main.rs @@ -23,7 +23,7 @@ use tracing_appender::rolling; use tracing_subscriber::prelude::*; use tracing_subscriber::Layer; -fn init_tracing(config: &config::Logging, tokio_console: bool) { +fn init_tracing(config: &config::Logging) { // Enable logging to journald. let journald = config.journald.enabled.then(|| { tracing_journald::layer().expect("couldn't connect to journald") @@ -78,29 +78,38 @@ fn init_tracing(config: &config::Logging, tokio_console: bool) { layer.with_filter(log_level_filter) }); - // Enable tokio-console instrumentation. - let console = tokio_console.then(console_subscriber::spawn); - // Configure the tracing fmt layer. - let env_filter = tracing_subscriber::EnvFilter::builder() - .with_default_directive("holo=debug".parse().unwrap()) - .from_env_lossy(); - let env_filter = match tokio_console { - true => { - // Enable targets needed by the console. - env_filter - .add_directive("tokio=trace".parse().unwrap()) - .add_directive("runtime=trace".parse().unwrap()) - } - false => env_filter, - }; - tracing_subscriber::registry() - .with(env_filter) - .with(journald) - .with(file) - .with(stdout) - .with(console) - .init(); + #[cfg(feature = "tokio_console")] + { + // Enable tokio-console instrumentation. + let console = console_subscriber::spawn(); + let env_filter = tracing_subscriber::EnvFilter::builder() + .with_default_directive("holo=debug".parse().unwrap()) + .from_env_lossy(); + // Enable targets needed by the console. + let env_filter = env_filter + .add_directive("tokio=trace".parse().unwrap()) + .add_directive("runtime=trace".parse().unwrap()); + tracing_subscriber::registry() + .with(env_filter) + .with(journald) + .with(file) + .with(stdout) + .with(console) + .init(); + } + #[cfg(not(feature = "tokio_console"))] + { + let env_filter = tracing_subscriber::EnvFilter::builder() + .with_default_directive("holo=debug".parse().unwrap()) + .from_env_lossy(); + tracing_subscriber::registry() + .with(env_filter) + .with(journald) + .with(file) + .with(stdout) + .init(); + } } fn init_db>( @@ -174,7 +183,7 @@ fn main() { } // Initialize tracing. - init_tracing(&config.logging, config.tokio_console.enabled); + init_tracing(&config.logging); // Initialize non-volatile storage. let db = init_db(&config.database_path) From dd3523f0be06d3ca3167f3c12d33dd3ec4738d1e Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 5 Jul 2024 21:29:45 -0300 Subject: [PATCH 08/14] build: bump nix to 0.29 and enable only required features Starting from version 0.27, nix disables all crate features by default, requiring users to opt-in to the features they need. This change helps by building only the necessary parts of the crate, reducing both binary size and build time. Signed-off-by: Renato Westphal --- Cargo.toml | 2 +- holo-bfd/src/network.rs | 2 +- holo-ospf/src/network.rs | 2 +- holo-ospf/src/ospfv2/network.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9323d9a6..2a33e877 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ itertools = "0.10" libc = "0.2" maplit = "1.0" md5 = "0.7" -nix = "0.26" +nix = { version = "0.29", features = ["fs", "net", "socket", "uio", "user"] } netlink-packet-core = "0.7" netlink-packet-route = "0.17" netlink-sys = "0.8" diff --git a/holo-bfd/src/network.rs b/holo-bfd/src/network.rs index 9945e7bf..399ccc89 100644 --- a/holo-bfd/src/network.rs +++ b/holo-bfd/src/network.rs @@ -214,7 +214,7 @@ pub(crate) async fn read_loop( Ok(msg) => { // Retrieve source and destination addresses. let src = get_packet_src(msg.address.as_ref()); - let dst = get_packet_dst(msg.cmsgs()); + let dst = get_packet_dst(msg.cmsgs().unwrap()); Ok((src, dst, msg.bytes)) } Err(errno) => Err(errno.into()), diff --git a/holo-ospf/src/network.rs b/holo-ospf/src/network.rs index cc2ef95b..eb16e425 100644 --- a/holo-ospf/src/network.rs +++ b/holo-ospf/src/network.rs @@ -212,7 +212,7 @@ where .address .as_ref() .map(|addr| V::src_from_sockaddr(addr)); - let dst = V::get_cmsg_data(msg.cmsgs()); + let dst = V::get_cmsg_data(msg.cmsgs().unwrap()); Ok((src, dst, msg.bytes)) } Err(errno) => Err(errno.into()), diff --git a/holo-ospf/src/ospfv2/network.rs b/holo-ospf/src/ospfv2/network.rs index 4e3d7dec..dfb9442a 100644 --- a/holo-ospf/src/ospfv2/network.rs +++ b/holo-ospf/src/ospfv2/network.rs @@ -147,7 +147,7 @@ impl NetworkVersion for Ospfv2 { } fn src_from_sockaddr(sockaddr: &SockaddrIn) -> Ipv4Addr { - Ipv4Addr::from(sockaddr.ip()) + sockaddr.ip() } fn validate_ip_hdr(buf: &mut Bytes) -> DecodeResult<()> { From f54a0d7baff0339548951e5ac6cb7aaba7ac8e2f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 8 Jul 2024 13:36:08 -0300 Subject: [PATCH 09/14] chore: upgrade dependency from yang2 to yang3 Signed-off-by: Renato Westphal --- Cargo.toml | 2 +- INSTALL.md | 2 +- holo-bfd/Cargo.toml | 2 +- holo-bgp/Cargo.toml | 2 +- holo-bgp/src/northbound/rpc.rs | 2 +- holo-daemon/Cargo.toml | 2 +- holo-daemon/src/northbound/client/api.rs | 2 +- holo-daemon/src/northbound/client/gnmi.rs | 4 ++-- holo-daemon/src/northbound/client/grpc.rs | 2 +- holo-daemon/src/northbound/core.rs | 2 +- holo-daemon/src/northbound/error.rs | 6 +++--- holo-interface/Cargo.toml | 2 +- holo-keychain/Cargo.toml | 2 +- holo-ldp/Cargo.toml | 2 +- holo-ldp/src/northbound/rpc.rs | 2 +- holo-northbound/Cargo.toml | 4 ++-- holo-northbound/build.rs | 6 +++--- holo-northbound/src/api.rs | 2 +- holo-northbound/src/configuration.rs | 4 ++-- holo-northbound/src/error.rs | 4 ++-- holo-northbound/src/lib.rs | 2 +- holo-northbound/src/notification.rs | 2 +- holo-northbound/src/rpc.rs | 4 ++-- holo-northbound/src/state.rs | 4 ++-- holo-ospf/Cargo.toml | 2 +- holo-ospf/src/northbound/configuration.rs | 2 +- holo-ospf/src/northbound/rpc.rs | 2 +- holo-policy/Cargo.toml | 2 +- holo-protocol/Cargo.toml | 2 +- holo-protocol/src/test/stub/collector.rs | 2 +- holo-protocol/src/test/stub/northbound.rs | 2 +- holo-rip/Cargo.toml | 2 +- holo-routing/Cargo.toml | 2 +- holo-routing/src/northbound/rpc.rs | 2 +- holo-tools/Cargo.toml | 2 +- holo-tools/src/yang_callbacks.rs | 4 ++-- holo-tools/src/yang_coverage.rs | 4 ++-- holo-tools/src/yang_deviations.rs | 2 +- holo-utils/Cargo.toml | 2 +- holo-utils/src/yang.rs | 6 +++--- holo-yang/Cargo.toml | 4 ++-- holo-yang/modules/deviations/ietf-rip-holo-deviations.yang | 6 ++++++ holo-yang/src/lib.rs | 4 ++-- holo-yang/src/serde/data_tree.rs | 2 +- 44 files changed, 65 insertions(+), 59 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a33e877..0c2e5def 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,7 @@ tonic = { version = "0.11", features = ["tls"] } tonic-build = "0.11" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } -yang2 = { version = "0.13", features = ["bundled"] } +yang3 = { version = "0.1", features = ["bundled"] } [workspace.lints.rust] rust_2018_idioms = { level = "warn", priority = -1 } diff --git a/INSTALL.md b/INSTALL.md index 52cb51e3..cbf452ea 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -17,7 +17,7 @@ $ git clone https://github.com/holo-routing/holo-cli.git 3. Install build dependencies: -Holo requires a few dependencies for building and embedding the libyang2 library. +Holo requires a few dependencies for building and embedding the libyang library. You can install them using your system's package manager. For example, on Debian-based systems: ``` diff --git a/holo-bfd/Cargo.toml b/holo-bfd/Cargo.toml index ab69ffe9..20318258 100644 --- a/holo-bfd/Cargo.toml +++ b/holo-bfd/Cargo.toml @@ -25,7 +25,7 @@ serde_json.workspace = true socket2.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-protocol = { path = "../holo-protocol" } diff --git a/holo-bgp/Cargo.toml b/holo-bgp/Cargo.toml index 3ed58b4e..8532bff3 100644 --- a/holo-bgp/Cargo.toml +++ b/holo-bgp/Cargo.toml @@ -26,7 +26,7 @@ serde_json.workspace = true serde_with.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-protocol = { path = "../holo-protocol" } diff --git a/holo-bgp/src/northbound/rpc.rs b/holo-bgp/src/northbound/rpc.rs index d92ca4ff..f05988fc 100644 --- a/holo-bgp/src/northbound/rpc.rs +++ b/holo-bgp/src/northbound/rpc.rs @@ -9,7 +9,7 @@ use std::sync::LazyLock as Lazy; use holo_northbound::rpc::{Callbacks, CallbacksBuilder, Provider}; use holo_northbound::yang::control_plane_protocol::bgp; use holo_utils::yang::DataNodeRefExt; -use yang2::data::Data; +use yang3::data::Data; use crate::instance::Instance; diff --git a/holo-daemon/Cargo.toml b/holo-daemon/Cargo.toml index 43a42c3d..b49adc4b 100644 --- a/holo-daemon/Cargo.toml +++ b/holo-daemon/Cargo.toml @@ -28,7 +28,7 @@ tokio.workspace = true tonic.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -yang2.workspace = true +yang3.workspace = true holo-interface = { path = "../holo-interface", optional = true } holo-bfd = { path = "../holo-bfd", optional = true } diff --git a/holo-daemon/src/northbound/client/api.rs b/holo-daemon/src/northbound/client/api.rs index f0a41bfc..99453ef5 100644 --- a/holo-daemon/src/northbound/client/api.rs +++ b/holo-daemon/src/northbound/client/api.rs @@ -5,7 +5,7 @@ // use holo_utils::Responder; -use yang2::data::{DataDiff, DataTree}; +use yang3::data::{DataDiff, DataTree}; use crate::northbound::core::Transaction; use crate::northbound::Result; diff --git a/holo-daemon/src/northbound/client/gnmi.rs b/holo-daemon/src/northbound/client/gnmi.rs index e4689fe1..f2f31cb5 100644 --- a/holo-daemon/src/northbound/client/gnmi.rs +++ b/holo-daemon/src/northbound/client/gnmi.rs @@ -14,8 +14,8 @@ use tokio_stream::wrappers::ReceiverStream; use tonic::transport::{Server, ServerTlsConfig}; use tonic::{Request, Response, Status, Streaming}; use tracing::{debug, debug_span, error, trace}; -use yang2::data::{Data, DataFormat, DataPrinterFlags, DataTree}; -use yang2::schema::SchemaNodeKind; +use yang3::data::{Data, DataFormat, DataPrinterFlags, DataTree}; +use yang3::schema::SchemaNodeKind; use crate::config; use crate::northbound::client::api; diff --git a/holo-daemon/src/northbound/client/grpc.rs b/holo-daemon/src/northbound/client/grpc.rs index d67b6fee..8fc118e2 100644 --- a/holo-daemon/src/northbound/client/grpc.rs +++ b/holo-daemon/src/northbound/client/grpc.rs @@ -14,7 +14,7 @@ use tokio::sync::oneshot; use tonic::transport::{Server, ServerTlsConfig}; use tonic::{Request, Response, Status}; use tracing::{debug, debug_span, error, trace}; -use yang2::data::{ +use yang3::data::{ Data, DataDiff, DataFormat, DataOperation, DataParserFlags, DataPrinterFlags, DataTree, DataValidationFlags, }; diff --git a/holo-daemon/src/northbound/core.rs b/holo-daemon/src/northbound/core.rs index 23c8546c..228b3ae1 100644 --- a/holo-daemon/src/northbound/core.rs +++ b/holo-daemon/src/northbound/core.rs @@ -24,7 +24,7 @@ use pickledb::PickleDb; use serde::{Deserialize, Serialize}; use tokio::sync::{broadcast, mpsc, oneshot}; use tracing::{debug, error, info, instrument, trace, warn}; -use yang2::data::{ +use yang3::data::{ Data, DataDiffFlags, DataFormat, DataPrinterFlags, DataTree, DataValidationFlags, }; diff --git a/holo-daemon/src/northbound/error.rs b/holo-daemon/src/northbound/error.rs index b0d5cefd..8d85db40 100644 --- a/holo-daemon/src/northbound/error.rs +++ b/holo-daemon/src/northbound/error.rs @@ -16,9 +16,9 @@ pub type Result = std::result::Result; // #[derive(Debug)] pub enum Error { - YangInvalidPath(yang2::Error), - YangInvalidData(yang2::Error), - YangInternal(yang2::Error), + YangInvalidPath(yang3::Error), + YangInvalidData(yang3::Error), + YangInternal(yang3::Error), TransactionValidation(northbound::error::Error), TransactionPreparation(northbound::error::Error), TransactionIdNotFound(u32), diff --git a/holo-interface/Cargo.toml b/holo-interface/Cargo.toml index 46509c10..a5bddb87 100644 --- a/holo-interface/Cargo.toml +++ b/holo-interface/Cargo.toml @@ -20,7 +20,7 @@ netlink-sys.workspace = true rtnetlink.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-utils = { path = "../holo-utils" } diff --git a/holo-keychain/Cargo.toml b/holo-keychain/Cargo.toml index a89a8e53..770dad1c 100644 --- a/holo-keychain/Cargo.toml +++ b/holo-keychain/Cargo.toml @@ -12,7 +12,7 @@ derive-new.workspace = true enum-as-inner.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-utils = { path = "../holo-utils" } diff --git a/holo-ldp/Cargo.toml b/holo-ldp/Cargo.toml index 989f91e4..d8e032c2 100644 --- a/holo-ldp/Cargo.toml +++ b/holo-ldp/Cargo.toml @@ -24,7 +24,7 @@ serde_with.workspace = true socket2.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-protocol = { path = "../holo-protocol" } diff --git a/holo-ldp/src/northbound/rpc.rs b/holo-ldp/src/northbound/rpc.rs index 2076ffea..25326ebd 100644 --- a/holo-ldp/src/northbound/rpc.rs +++ b/holo-ldp/src/northbound/rpc.rs @@ -10,7 +10,7 @@ use std::sync::LazyLock as Lazy; use holo_northbound::rpc::{Callbacks, CallbacksBuilder, Provider}; use holo_northbound::yang; use holo_utils::yang::DataNodeRefExt; -use yang2::data::Data; +use yang3::data::Data; use crate::discovery; use crate::instance::{Instance, InstanceUpView}; diff --git a/holo-northbound/Cargo.toml b/holo-northbound/Cargo.toml index 2cec32d9..18760f31 100644 --- a/holo-northbound/Cargo.toml +++ b/holo-northbound/Cargo.toml @@ -17,7 +17,7 @@ serde.workspace = true serde_json.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-utils = { path = "../holo-utils" } holo-yang = { path = "../holo-yang" } @@ -28,7 +28,7 @@ holo-utils = { path = "../holo-utils" } [build-dependencies] check_keyword.workspace = true convert_case.workspace = true -yang2.workspace = true +yang3.workspace = true holo-yang = { path = "../holo-yang" } [lints] diff --git a/holo-northbound/build.rs b/holo-northbound/build.rs index 0a99d620..d349b8d5 100644 --- a/holo-northbound/build.rs +++ b/holo-northbound/build.rs @@ -14,7 +14,7 @@ use check_keyword::CheckKeyword; use convert_case::{Boundary, Case, Casing}; use holo_yang as yang; use holo_yang::YANG_IMPLEMENTED_MODULES; -use yang2::schema::{ +use yang3::schema::{ DataValue, DataValueType, SchemaLeafType, SchemaNode, SchemaNodeKind, SchemaPathFormat, }; @@ -28,8 +28,8 @@ use chrono::{DateTime, Utc}; use holo_yang::{YangObject, YangPath, YANG_CTX}; use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network}; use itertools::Itertools; -use yang2::data::DataNodeRef; -use yang2::schema::SchemaModule; +use yang3::data::DataNodeRef; +use yang3::schema::SchemaModule; fn binary_to_yang(value: &[u8]) -> String { use base64::Engine; diff --git a/holo-northbound/src/api.rs b/holo-northbound/src/api.rs index 625d717f..d02c7903 100644 --- a/holo-northbound/src/api.rs +++ b/holo-northbound/src/api.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use holo_utils::Responder; use serde::{Deserialize, Serialize}; -use yang2::data::DataTree; +use yang3::data::DataTree; use crate::configuration::{CommitPhase, ConfigChanges}; use crate::error::Error; diff --git a/holo-northbound/src/configuration.rs b/holo-northbound/src/configuration.rs index c4736860..4bddd0e6 100644 --- a/holo-northbound/src/configuration.rs +++ b/holo-northbound/src/configuration.rs @@ -12,8 +12,8 @@ use holo_utils::yang::SchemaNodeExt; use holo_yang::YangPath; use serde::{Deserialize, Serialize}; use tokio::sync::oneshot; -use yang2::data::{Data, DataDiff, DataDiffOp, DataNodeRef, DataTree}; -use yang2::schema::SchemaNodeKind; +use yang3::data::{Data, DataDiff, DataDiffOp, DataNodeRef, DataTree}; +use yang3::schema::SchemaNodeKind; use crate::debug::Debug; use crate::error::Error; diff --git a/holo-northbound/src/error.rs b/holo-northbound/src/error.rs index a49fc87f..0dfaf36d 100644 --- a/holo-northbound/src/error.rs +++ b/holo-northbound/src/error.rs @@ -14,8 +14,8 @@ pub enum Error { RpcNotFound, RpcRelay(String), RpcCallback(String), - YangInvalidPath(yang2::Error), - YangInvalidData(yang2::Error), + YangInvalidPath(yang3::Error), + YangInvalidData(yang3::Error), } // ===== impl Error ===== diff --git a/holo-northbound/src/lib.rs b/holo-northbound/src/lib.rs index b85af914..822f5b52 100644 --- a/holo-northbound/src/lib.rs +++ b/holo-northbound/src/lib.rs @@ -24,7 +24,7 @@ use derive_new::new; use holo_utils::{Receiver, Sender, UnboundedReceiver, UnboundedSender}; use serde::{Deserialize, Serialize}; use tracing::Span; -use yang2::schema::{DataValueType, SchemaNode, SchemaNodeKind}; +use yang3::schema::{DataValueType, SchemaNode, SchemaNodeKind}; use crate::debug::Debug; diff --git a/holo-northbound/src/notification.rs b/holo-northbound/src/notification.rs index 90a427ec..e7363245 100644 --- a/holo-northbound/src/notification.rs +++ b/holo-northbound/src/notification.rs @@ -5,7 +5,7 @@ // use holo_yang::{YangObject, YANG_CTX}; -use yang2::data::DataTree; +use yang3::data::DataTree; use crate::api::provider::Notification; use crate::NbProviderSender; diff --git a/holo-northbound/src/rpc.rs b/holo-northbound/src/rpc.rs index f2919eb3..61fffd30 100644 --- a/holo-northbound/src/rpc.rs +++ b/holo-northbound/src/rpc.rs @@ -11,8 +11,8 @@ use std::pin::Pin; use holo_utils::yang::SchemaNodeExt; use holo_yang::YangPath; use tokio::sync::oneshot; -use yang2::data::{DataNodeRef, DataTree}; -use yang2::schema::SchemaNodeKind; +use yang3::data::{DataNodeRef, DataTree}; +use yang3::schema::SchemaNodeKind; use crate::debug::Debug; use crate::error::Error; diff --git a/holo-northbound/src/state.rs b/holo-northbound/src/state.rs index eb75a57b..29af0947 100644 --- a/holo-northbound/src/state.rs +++ b/holo-northbound/src/state.rs @@ -11,8 +11,8 @@ use derive_new::new; use holo_utils::yang::SchemaNodeExt; use holo_yang::{YangObject, YangPath, YANG_CTX}; use tokio::sync::oneshot; -use yang2::data::{DataNodeRef, DataTree}; -use yang2::schema::{SchemaModule, SchemaNode, SchemaNodeKind}; +use yang3::data::{DataNodeRef, DataTree}; +use yang3::schema::{SchemaModule, SchemaNode, SchemaNodeKind}; use crate::error::Error; use crate::{api, CallbackKey, CallbackOp, NbDaemonSender, ProviderBase}; diff --git a/holo-ospf/Cargo.toml b/holo-ospf/Cargo.toml index 08579d34..21569b02 100644 --- a/holo-ospf/Cargo.toml +++ b/holo-ospf/Cargo.toml @@ -33,7 +33,7 @@ smallvec.workspace = true socket2.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-protocol = { path = "../holo-protocol" } diff --git a/holo-ospf/src/northbound/configuration.rs b/holo-ospf/src/northbound/configuration.rs index 06cca84e..641e05b3 100644 --- a/holo-ospf/src/northbound/configuration.rs +++ b/holo-ospf/src/northbound/configuration.rs @@ -21,7 +21,7 @@ use holo_utils::ibus::IbusMsg; use holo_utils::ip::{AddressFamily, IpAddrKind, IpNetworkKind}; use holo_utils::yang::DataNodeRefExt; use holo_yang::{ToYang, TryFromYang}; -use yang2::data::Data; +use yang3::data::Data; use crate::area::{self, AreaType}; use crate::collections::{AreaIndex, InterfaceIndex}; diff --git a/holo-ospf/src/northbound/rpc.rs b/holo-ospf/src/northbound/rpc.rs index 9c50f882..b5ff5a61 100644 --- a/holo-ospf/src/northbound/rpc.rs +++ b/holo-ospf/src/northbound/rpc.rs @@ -9,7 +9,7 @@ use std::sync::LazyLock as Lazy; use holo_northbound::rpc::{Callbacks, CallbacksBuilder, Provider}; use holo_northbound::yang; use holo_utils::yang::DataNodeRefExt; -use yang2::data::Data; +use yang3::data::Data; use crate::instance::{Instance, InstanceArenas, InstanceUpView}; use crate::neighbor::nsm; diff --git a/holo-policy/Cargo.toml b/holo-policy/Cargo.toml index cda5c469..71385e1c 100644 --- a/holo-policy/Cargo.toml +++ b/holo-policy/Cargo.toml @@ -11,7 +11,7 @@ derive-new.workspace = true enum-as-inner.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-utils = { path = "../holo-utils" } diff --git a/holo-protocol/Cargo.toml b/holo-protocol/Cargo.toml index 395e07f5..2dff9b45 100644 --- a/holo-protocol/Cargo.toml +++ b/holo-protocol/Cargo.toml @@ -13,7 +13,7 @@ serde_json.workspace = true tokio.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-utils = { path = "../holo-utils" } diff --git a/holo-protocol/src/test/stub/collector.rs b/holo-protocol/src/test/stub/collector.rs index dc01bbc1..0b3224d5 100644 --- a/holo-protocol/src/test/stub/collector.rs +++ b/holo-protocol/src/test/stub/collector.rs @@ -9,7 +9,7 @@ use std::sync::{Arc, Mutex}; use holo_northbound::NbProviderReceiver; use holo_utils::ibus::IbusReceiver; use holo_utils::Receiver; -use yang2::data::{Data, DataFormat, DataPrinterFlags}; +use yang3::data::{Data, DataFormat, DataPrinterFlags}; use crate::ProtocolInstance; diff --git a/holo-protocol/src/test/stub/northbound.rs b/holo-protocol/src/test/stub/northbound.rs index fc31793f..3ae8b1e1 100644 --- a/holo-protocol/src/test/stub/northbound.rs +++ b/holo-protocol/src/test/stub/northbound.rs @@ -10,7 +10,7 @@ use holo_northbound::configuration::{self, CommitPhase, ConfigChanges}; use holo_northbound::{api, NbDaemonSender}; use holo_yang::YANG_CTX; use tokio::sync::oneshot; -use yang2::data::{ +use yang3::data::{ Data, DataDiff, DataDiffFlags, DataFormat, DataOperation, DataParserFlags, DataPrinterFlags, DataTree, DataValidationFlags, }; diff --git a/holo-rip/Cargo.toml b/holo-rip/Cargo.toml index ca115a5d..b537a276 100644 --- a/holo-rip/Cargo.toml +++ b/holo-rip/Cargo.toml @@ -24,7 +24,7 @@ serde.workspace = true serde_json.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-protocol = { path = "../holo-protocol" } diff --git a/holo-routing/Cargo.toml b/holo-routing/Cargo.toml index 7b560c1f..d0dbfc89 100644 --- a/holo-routing/Cargo.toml +++ b/holo-routing/Cargo.toml @@ -19,7 +19,7 @@ regex.workspace = true rtnetlink.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-northbound = { path = "../holo-northbound" } holo-protocol = { path = "../holo-protocol" } diff --git a/holo-routing/src/northbound/rpc.rs b/holo-routing/src/northbound/rpc.rs index f281c4ee..b4ea1c96 100644 --- a/holo-routing/src/northbound/rpc.rs +++ b/holo-routing/src/northbound/rpc.rs @@ -9,7 +9,7 @@ use holo_northbound::yang::control_plane_protocol; use holo_northbound::{CallbackKey, NbDaemonSender}; use holo_utils::protocol::Protocol; use holo_utils::yang::DataNodeRefExt; -use yang2::data::DataNodeRef; +use yang3::data::DataNodeRef; use crate::Master; diff --git a/holo-tools/Cargo.toml b/holo-tools/Cargo.toml index 5045752b..d700a3e4 100644 --- a/holo-tools/Cargo.toml +++ b/holo-tools/Cargo.toml @@ -13,7 +13,7 @@ num-traits.workspace = true serde_json.workspace = true similar.workspace = true tokio.workspace = true -yang2.workspace = true +yang3.workspace = true holo-bfd = { path = "../holo-bfd", features = ["testing"] } holo-bgp = { path = "../holo-bgp", features = ["testing"] } diff --git a/holo-tools/src/yang_callbacks.rs b/holo-tools/src/yang_callbacks.rs index 8c457db5..915a5cd5 100644 --- a/holo-tools/src/yang_callbacks.rs +++ b/holo-tools/src/yang_callbacks.rs @@ -9,8 +9,8 @@ use clap::{App, Arg}; use convert_case::{Boundary, Case, Casing}; use holo_northbound::CallbackOp; use holo_yang as yang; -use yang2::context::Context; -use yang2::schema::{SchemaModule, SchemaNode, SchemaNodeKind}; +use yang3::context::Context; +use yang3::schema::{SchemaModule, SchemaNode, SchemaNodeKind}; fn snode_module(snode: &SchemaNode<'_>) -> String { let snodes = snode.inclusive_ancestors().collect::>(); diff --git a/holo-tools/src/yang_coverage.rs b/holo-tools/src/yang_coverage.rs index c64e86e5..cdd66db8 100644 --- a/holo-tools/src/yang_coverage.rs +++ b/holo-tools/src/yang_coverage.rs @@ -9,8 +9,8 @@ use std::collections::BTreeMap; use clap::{App, Arg}; use holo_yang as yang; use num_traits::cast::AsPrimitive; -use yang2::context::Context; -use yang2::schema::{SchemaNodeKind, SchemaOutputFormat, SchemaPrinterFlags}; +use yang3::context::Context; +use yang3::schema::{SchemaNodeKind, SchemaOutputFormat, SchemaPrinterFlags}; #[derive(Debug, Default)] struct NodeCounters { diff --git a/holo-tools/src/yang_deviations.rs b/holo-tools/src/yang_deviations.rs index 9a86b90c..55bfc5a3 100644 --- a/holo-tools/src/yang_deviations.rs +++ b/holo-tools/src/yang_deviations.rs @@ -6,7 +6,7 @@ use clap::{App, Arg}; use holo_yang as yang; -use yang2::schema::SchemaNode; +use yang3::schema::SchemaNode; // Generate fully-prefixed schema path. fn gen_fully_prefixed_path(snode: &SchemaNode<'_>) -> String { diff --git a/holo-utils/Cargo.toml b/holo-utils/Cargo.toml index 514d22c9..9a9f71ab 100644 --- a/holo-utils/Cargo.toml +++ b/holo-utils/Cargo.toml @@ -28,7 +28,7 @@ serde_json.workspace = true socket2.workspace = true tokio.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true holo-yang = { path = "../holo-yang" } diff --git a/holo-utils/src/yang.rs b/holo-utils/src/yang.rs index a174260d..fc6b30a2 100644 --- a/holo-utils/src/yang.rs +++ b/holo-utils/src/yang.rs @@ -10,9 +10,9 @@ use std::str::FromStr; use holo_yang::TryFromYang; use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network}; -use yang2::context::Context; -use yang2::data::{Data, DataNodeRef}; -use yang2::schema::{DataValue, SchemaNode, SchemaPathFormat}; +use yang3::context::Context; +use yang3::data::{Data, DataNodeRef}; +use yang3::schema::{DataValue, SchemaNode, SchemaPathFormat}; use crate::ip::AddressFamily; diff --git a/holo-yang/Cargo.toml b/holo-yang/Cargo.toml index fdeef09b..29fdce3d 100644 --- a/holo-yang/Cargo.toml +++ b/holo-yang/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "holo-yang" -version = "0.4.2" +version = "0.5.0" authors.workspace = true license.workspace = true edition.workspace = true @@ -11,7 +11,7 @@ description = "YANG module of Holo Routing, including embedded YANG models and u maplit.workspace = true serde.workspace = true tracing.workspace = true -yang2.workspace = true +yang3.workspace = true [lints] workspace = true diff --git a/holo-yang/modules/deviations/ietf-rip-holo-deviations.yang b/holo-yang/modules/deviations/ietf-rip-holo-deviations.yang index a9178812..9e15b4a3 100644 --- a/holo-yang/modules/deviations/ietf-rip-holo-deviations.yang +++ b/holo-yang/modules/deviations/ietf-rip-holo-deviations.yang @@ -368,6 +368,12 @@ module ietf-rip-holo-deviations { } */ + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/rip:rip/rip:interfaces/rip:interface/rip:timers" { + deviate delete { + must 'invalid-interval >= (update-interval * 3)'; + } + } + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/rip:rip/rip:interfaces/rip:interface/rip:timers/rip:update-interval" { deviate not-supported; } diff --git a/holo-yang/src/lib.rs b/holo-yang/src/lib.rs index e21e1338..7e1d1a92 100644 --- a/holo-yang/src/lib.rs +++ b/holo-yang/src/lib.rs @@ -11,10 +11,10 @@ use std::collections::HashMap; use std::sync::{Arc, LazyLock as Lazy, OnceLock}; use maplit::hashmap; -use yang2::context::{ +use yang3::context::{ Context, ContextFlags, EmbeddedModuleKey, EmbeddedModules, }; -use yang2::data::DataNodeRef; +use yang3::data::DataNodeRef; // Global YANG context. pub static YANG_CTX: OnceLock> = OnceLock::new(); diff --git a/holo-yang/src/serde/data_tree.rs b/holo-yang/src/serde/data_tree.rs index 671a6fe8..3402abc7 100644 --- a/holo-yang/src/serde/data_tree.rs +++ b/holo-yang/src/serde/data_tree.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use serde::{Deserialize, Serializer}; -use yang2::data::{ +use yang3::data::{ Data, DataFormat, DataParserFlags, DataPrinterFlags, DataTree, DataValidationFlags, }; From f2b3bbd2377a5d99e5451bc01a1576a9b8e5144a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 9 Jul 2024 11:01:41 -0300 Subject: [PATCH 10/14] northbound: use `Cow` for "date-and-time" leaves Update the "date-and-time" leaves to use `Cow`, similar to other leaf types. This change allows for both owned and borrowed values, providing greater flexibility. Signed-off-by: Renato Westphal --- Cargo.toml | 1 + holo-bfd/src/northbound/notification.rs | 6 ++++-- holo-bfd/src/northbound/state.rs | 12 ++++++------ holo-bgp/src/northbound/notification.rs | 4 ++-- holo-bgp/src/northbound/state.rs | 6 +++--- holo-interface/src/netlink.rs | 2 -- holo-keychain/src/northbound/state.rs | 6 +++++- holo-ldp/src/northbound/state.rs | 8 ++++---- holo-northbound/build.rs | 2 +- holo-ospf/src/northbound/state.rs | 8 ++++---- holo-rip/src/northbound/state.rs | 14 ++++++++++---- holo-routing/src/northbound/state.rs | 2 +- 12 files changed, 41 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0c2e5def..9c6736da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,7 @@ unsafe_code = "forbid" [workspace.lints.clippy] borrowed_box = "allow" manual_range_contains = "allow" +single_match = "allow" too_many_arguments = "allow" [profile.release] diff --git a/holo-bfd/src/northbound/notification.rs b/holo-bfd/src/northbound/notification.rs index 96b5a8d0..43979ae4 100644 --- a/holo-bfd/src/northbound/notification.rs +++ b/holo-bfd/src/northbound/notification.rs @@ -44,7 +44,8 @@ fn state_change_singlehop( time_of_last_state_change: sess .statistics .last_state_change_time - .as_ref(), + .as_ref() + .map(Cow::Borrowed), dest_addr: Some(Cow::Borrowed(dst)), source_addr: sess.config.src.as_ref().map(Cow::Borrowed), session_index: Some(sess.id as u32), @@ -71,7 +72,8 @@ fn state_change_multihop( time_of_last_state_change: sess .statistics .last_state_change_time - .as_ref(), + .as_ref() + .map(Cow::Borrowed), dest_addr: Some(Cow::Borrowed(dst)), source_addr: Some(Cow::Borrowed(src)), session_index: Some(sess.id as u32), diff --git a/holo-bfd/src/northbound/state.rs b/holo-bfd/src/northbound/state.rs index cde5e2f9..10850621 100644 --- a/holo-bfd/src/northbound/state.rs +++ b/holo-bfd/src/northbound/state.rs @@ -111,9 +111,9 @@ fn load_callbacks() -> Callbacks { use bfd::ip_mh::session_groups::session_group::sessions::session_statistics::SessionStatistics; let sess = args.list_entry.as_session().unwrap(); Box::new(SessionStatistics { - create_time: Some(&sess.statistics.create_time).ignore_in_testing(), - last_down_time: sess.statistics.last_down_time.as_ref().ignore_in_testing(), - last_up_time: sess.statistics.last_up_time.as_ref().ignore_in_testing(), + create_time: Some(Cow::Borrowed(&sess.statistics.create_time)).ignore_in_testing(), + last_down_time: sess.statistics.last_down_time.as_ref().map(Cow::Borrowed).ignore_in_testing(), + last_up_time: sess.statistics.last_up_time.as_ref().map(Cow::Borrowed).ignore_in_testing(), down_count: Some(sess.statistics.down_count).ignore_in_testing(), admin_down_count: Some(sess.statistics.admin_down_count).ignore_in_testing(), receive_packet_count: Some(sess.statistics.rx_packet_count).ignore_in_testing(), @@ -176,9 +176,9 @@ fn load_callbacks() -> Callbacks { use bfd::ip_sh::sessions::session::session_statistics::SessionStatistics; let sess = args.list_entry.as_session().unwrap(); Box::new(SessionStatistics { - create_time: Some(&sess.statistics.create_time).ignore_in_testing(), - last_down_time: sess.statistics.last_down_time.as_ref().ignore_in_testing(), - last_up_time: sess.statistics.last_up_time.as_ref().ignore_in_testing(), + create_time: Some(Cow::Borrowed(&sess.statistics.create_time)).ignore_in_testing(), + last_down_time: sess.statistics.last_down_time.as_ref().map(Cow::Borrowed).ignore_in_testing(), + last_up_time: sess.statistics.last_up_time.as_ref().map(Cow::Borrowed).ignore_in_testing(), down_count: Some(sess.statistics.down_count).ignore_in_testing(), admin_down_count: Some(sess.statistics.admin_down_count).ignore_in_testing(), receive_packet_count: Some(sess.statistics.rx_packet_count).ignore_in_testing(), diff --git a/holo-bgp/src/northbound/notification.rs b/holo-bgp/src/northbound/notification.rs index 360a2321..eae0b7d1 100644 --- a/holo-bgp/src/northbound/notification.rs +++ b/holo-bgp/src/northbound/notification.rs @@ -42,7 +42,7 @@ pub(crate) fn backward_transition( notification_received: nbr.notification_rcvd.as_ref().map( |(time, notif)| { Box::new(NotificationReceived { - last_notification: Some(time), + last_notification: Some(Cow::Borrowed(time)), last_error: Some(notif.to_yang()), last_error_code: Some(notif.error_code), last_error_subcode: Some(notif.error_subcode), @@ -52,7 +52,7 @@ pub(crate) fn backward_transition( notification_sent: nbr.notification_sent.as_ref().map( |(time, notif)| { Box::new(NotificationSent { - last_notification: Some(time), + last_notification: Some(Cow::Borrowed(time)), last_error: Some(notif.to_yang()), last_error_code: Some(notif.error_code), last_error_subcode: Some(notif.error_subcode), diff --git a/holo-bgp/src/northbound/state.rs b/holo-bgp/src/northbound/state.rs index 4e1a4ddd..7890f2f4 100644 --- a/holo-bgp/src/northbound/state.rs +++ b/holo-bgp/src/northbound/state.rs @@ -127,7 +127,7 @@ fn load_callbacks() -> Callbacks { identifier: nbr.identifier.map(Cow::Owned), dynamically_configured: None, session_state: Some(nbr.state.to_yang()), - last_established: nbr.last_established.as_ref().ignore_in_testing(), + last_established: nbr.last_established.as_ref().map(Cow::Borrowed).ignore_in_testing(), }) }) .path(bgp::neighbors::neighbor::timers::PATH) @@ -298,7 +298,7 @@ fn load_callbacks() -> Callbacks { let mut last_error_subcode = None; let mut last_error_data = None; if let Some((time, notif)) = &nbr.notification_rcvd { - last_notification = Some(time); + last_notification = Some(Cow::Borrowed(time)); last_error = Some(notif.to_yang()); last_error_code = Some(notif.error_code); last_error_subcode = Some(notif.error_subcode); @@ -322,7 +322,7 @@ fn load_callbacks() -> Callbacks { let mut last_error_subcode = None; let mut last_error_data = None; if let Some((time, notif)) = &nbr.notification_sent { - last_notification = Some(time); + last_notification = Some(Cow::Borrowed(time)); last_error = Some(notif.to_yang()); last_error_code = Some(notif.error_code); last_error_subcode = Some(notif.error_subcode); diff --git a/holo-interface/src/netlink.rs b/holo-interface/src/netlink.rs index d32952e5..a8488101 100644 --- a/holo-interface/src/netlink.rs +++ b/holo-interface/src/netlink.rs @@ -4,8 +4,6 @@ // SPDX-License-Identifier: MIT // -#![allow(clippy::single_match)] - use std::net::{Ipv4Addr, Ipv6Addr}; use capctl::caps::CapState; diff --git a/holo-keychain/src/northbound/state.rs b/holo-keychain/src/northbound/state.rs index 589d0909..6a9bdde5 100644 --- a/holo-keychain/src/northbound/state.rs +++ b/holo-keychain/src/northbound/state.rs @@ -4,6 +4,7 @@ // SPDX-License-Identifier: MIT // +use std::borrow::Cow; use std::sync::LazyLock as Lazy; use enum_as_inner::EnumAsInner; @@ -40,7 +41,10 @@ fn load_callbacks() -> Callbacks { let keychain = args.list_entry.as_keychain().unwrap(); Box::new(KeyChain { name: keychain.name.as_str().into(), - last_modified_timestamp: keychain.last_modified.as_ref(), + last_modified_timestamp: keychain + .last_modified + .as_ref() + .map(Cow::Borrowed), }) }) .path(key_chains::key_chain::key::PATH) diff --git a/holo-ldp/src/northbound/state.rs b/holo-ldp/src/northbound/state.rs index f4155f0a..72c46a08 100644 --- a/holo-ldp/src/northbound/state.rs +++ b/holo-ldp/src/northbound/state.rs @@ -211,7 +211,7 @@ fn load_callbacks() -> Callbacks { use mpls_ldp::discovery::interfaces::interface::address_families::ipv4::hello_adjacencies::hello_adjacency::statistics::Statistics; let adj = args.list_entry.as_interface_adj().unwrap(); Box::new(Statistics { - discontinuity_time: Some(&adj.discontinuity_time).ignore_in_testing(), + discontinuity_time: Some(Cow::Borrowed(&adj.discontinuity_time)).ignore_in_testing(), hello_received: Some(adj.hello_rcvd).ignore_in_testing(), hello_dropped: Some(adj.hello_dropped).ignore_in_testing(), }) @@ -256,7 +256,7 @@ fn load_callbacks() -> Callbacks { use mpls_ldp::discovery::targeted::address_families::ipv4::hello_adjacencies::hello_adjacency::statistics::Statistics; let adj = args.list_entry.as_targeted_nbr_adj().unwrap(); Box::new(Statistics { - discontinuity_time: Some(&adj.discontinuity_time).ignore_in_testing(), + discontinuity_time: Some(Cow::Borrowed(&adj.discontinuity_time)).ignore_in_testing(), hello_received: Some(adj.hello_rcvd).ignore_in_testing(), hello_dropped: Some(adj.hello_dropped).ignore_in_testing(), }) @@ -318,7 +318,7 @@ fn load_callbacks() -> Callbacks { use mpls_ldp::peers::peer::address_families::ipv4::hello_adjacencies::hello_adjacency::statistics::Statistics; let adj = args.list_entry.as_neighbor_adj().unwrap(); Box::new(Statistics { - discontinuity_time: Some(&adj.discontinuity_time).ignore_in_testing(), + discontinuity_time: Some(Cow::Borrowed(&adj.discontinuity_time)).ignore_in_testing(), hello_received: Some(adj.hello_rcvd).ignore_in_testing(), hello_dropped: Some(adj.hello_dropped).ignore_in_testing(), }) @@ -388,7 +388,7 @@ fn load_callbacks() -> Callbacks { let total_labels = nbr.rcvd_mappings.len(); let total_fec_label_bindings = nbr.rcvd_mappings.keys().map(|prefix| instance.state.as_ref().unwrap().fecs.get(prefix).unwrap()).filter(|fec| fec.is_nbr_nexthop(nbr)).count(); Box::new(Statistics { - discontinuity_time: nbr.statistics.discontinuity_time.as_ref().ignore_in_testing(), + discontinuity_time: nbr.statistics.discontinuity_time.as_ref().map(Cow::Borrowed).ignore_in_testing(), total_addresses: Some(total_addresses.saturating_into()), total_labels: Some(total_labels.saturating_into()), total_fec_label_bindings: Some(total_fec_label_bindings.saturating_into()), diff --git a/holo-northbound/build.rs b/holo-northbound/build.rs index d349b8d5..dc6db915 100644 --- a/holo-northbound/build.rs +++ b/holo-northbound/build.rs @@ -399,7 +399,7 @@ fn leaf_typedef_map(leaf_type: &SchemaLeafType<'_>) -> Option<&'static str> { Some("ip-prefix") => Some("Cow<'a, IpNetwork>"), Some("ipv4-prefix") => Some("Cow<'a, Ipv4Network>"), Some("ipv6-prefix") => Some("Cow<'a, Ipv6Network>"), - Some("date-and-time") => Some("&'a DateTime"), + Some("date-and-time") => Some("Cow<'a, DateTime>"), Some("timer-value-seconds16") => Some("Cow<'a, Duration>"), Some("timer-value-seconds32") => Some("Cow<'a, Duration>"), Some("timer-value-milliseconds") => Some("Cow<'a, Duration>"), diff --git a/holo-ospf/src/northbound/state.rs b/holo-ospf/src/northbound/state.rs index 58f0e374..35aaa3da 100644 --- a/holo-ospf/src/northbound/state.rs +++ b/holo-ospf/src/northbound/state.rs @@ -165,7 +165,7 @@ where let mut as_scope_lsa_count = None; let mut as_scope_lsa_chksum_sum = None; if let Some(state) = &instance.state { - discontinuity_time = Some(&state.discontinuity_time).ignore_in_testing(); + discontinuity_time = Some(Cow::Borrowed(&state.discontinuity_time)).ignore_in_testing(); originate_new_lsa_count = Some(state.orig_lsa_count).ignore_in_testing(); rx_new_lsas_count = Some(state.rx_lsa_count).ignore_in_testing(); as_scope_lsa_count = Some(state.lsdb.lsa_count()); @@ -303,7 +303,7 @@ where use ospf::areas::area::statistics::Statistics; let area = args.list_entry.as_area().unwrap(); Box::new(Statistics { - discontinuity_time: Some(&area.state.discontinuity_time).ignore_in_testing(), + discontinuity_time: Some(Cow::Borrowed(&area.state.discontinuity_time)).ignore_in_testing(), spf_runs_count: Some(area.state.spf_run_count).ignore_in_testing(), abr_count: Some(area.abr_count() as _), asbr_count: Some(area.asbr_count() as _), @@ -407,7 +407,7 @@ where use ospf::areas::area::interfaces::interface::statistics::Statistics; let iface = args.list_entry.as_interface().unwrap(); Box::new(Statistics { - discontinuity_time: Some(&iface.state.discontinuity_time).ignore_in_testing(), + discontinuity_time: Some(Cow::Borrowed(&iface.state.discontinuity_time)).ignore_in_testing(), if_event_count: Some(iface.state.event_count).ignore_in_testing(), link_scope_lsa_count: Some(iface.state.lsdb.lsa_count()), link_scope_lsa_cksum_sum: Some(iface.state.lsdb.cksum_sum()).ignore_in_testing(), @@ -485,7 +485,7 @@ where use ospf::areas::area::interfaces::interface::neighbors::neighbor::statistics::Statistics; let (_, nbr) = args.list_entry.as_neighbor().unwrap(); Box::new(Statistics { - discontinuity_time: Some(&nbr.discontinuity_time).ignore_in_testing(), + discontinuity_time: Some(Cow::Borrowed(&nbr.discontinuity_time)).ignore_in_testing(), nbr_event_count: Some(nbr.event_count).ignore_in_testing(), nbr_retrans_qlen: Some(nbr.lists.ls_rxmt.len() as u32), }) diff --git a/holo-rip/src/northbound/state.rs b/holo-rip/src/northbound/state.rs index b8446b11..78bd3ed4 100644 --- a/holo-rip/src/northbound/state.rs +++ b/holo-rip/src/northbound/state.rs @@ -114,7 +114,9 @@ where updates_sent = Some(iface.state.statistics.updates_sent); } Box::new(Statistics { - discontinuity_time: discontinuity_time.ignore_in_testing(), + discontinuity_time: discontinuity_time + .map(Cow::Borrowed) + .ignore_in_testing(), bad_packets_rcvd: bad_packets_rcvd.ignore_in_testing(), bad_routes_rcvd: bad_routes_rcvd.ignore_in_testing(), updates_sent: updates_sent.ignore_in_testing(), @@ -137,7 +139,9 @@ where responses_sent = Some(instance.state.statistics.responses_sent); } Box::new(Statistics { - discontinuity_time: discontinuity_time.ignore_in_testing(), + discontinuity_time: discontinuity_time + .map(Cow::Borrowed) + .ignore_in_testing(), requests_rcvd: requests_rcvd.ignore_in_testing(), requests_sent: requests_sent.ignore_in_testing(), responses_rcvd: responses_rcvd.ignore_in_testing(), @@ -167,7 +171,8 @@ fn load_callbacks_ripv2() -> Callbacks> { let nbr = args.list_entry.as_ipv4_neighbor().unwrap(); Box::new(Neighbor { ipv4_address: Cow::Borrowed(&nbr.addr), - last_update: Some(&nbr.last_update).ignore_in_testing(), + last_update: Some(Cow::Borrowed(&nbr.last_update)) + .ignore_in_testing(), bad_packets_rcvd: Some(nbr.bad_packets_rcvd) .ignore_in_testing(), bad_routes_rcvd: Some(nbr.bad_routes_rcvd).ignore_in_testing(), @@ -229,7 +234,8 @@ fn load_callbacks_ripng() -> Callbacks> { let nbr = args.list_entry.as_ipv6_neighbor().unwrap(); Box::new(Neighbor { ipv6_address: Cow::Borrowed(&nbr.addr), - last_update: Some(&nbr.last_update).ignore_in_testing(), + last_update: Some(Cow::Borrowed(&nbr.last_update)) + .ignore_in_testing(), bad_packets_rcvd: Some(nbr.bad_packets_rcvd) .ignore_in_testing(), bad_routes_rcvd: Some(nbr.bad_routes_rcvd).ignore_in_testing(), diff --git a/holo-routing/src/northbound/state.rs b/holo-routing/src/northbound/state.rs index 9c743d5e..68cfd1be 100644 --- a/holo-routing/src/northbound/state.rs +++ b/holo-routing/src/northbound/state.rs @@ -154,7 +154,7 @@ fn load_callbacks() -> Callbacks { route_preference, source_protocol, active: route.flags.contains(RouteFlags::ACTIVE).then_some(()), - last_updated: Some(&route.last_updated), + last_updated: Some(Cow::Borrowed(&route.last_updated)), ipv4_destination_prefix: dest.as_ipv4().copied().map(Cow::Borrowed), ipv6_destination_prefix: dest.as_ipv6().copied().map(Cow::Borrowed), mpls_enabled: None, From 7f4733700a21d6a8885ed37091a604ed26c84b45 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Mon, 8 Jul 2024 22:38:31 -0300 Subject: [PATCH 11/14] system: introduce the `holo-system` component Introduce `holo-system`, implementing the following subset of the ietf-system YANG module: module: ietf-system +--rw system | +--rw contact? string | +--rw hostname? inet:domain-name | +--rw location? string +--ro system-state +--ro platform | +--ro os-name? string | +--ro os-release? string | +--ro os-version? string | +--ro machine? string +--ro clock +--ro current-datetime? yang:date-and-time +--ro boot-datetime? yang:date-and-time The main motivation for this component is to provide a centralized place for storing hostname information and sharing it with protocol instances (both IS-IS and OSPF have TLVs for flooding hostname information). Additionally, including the hostname in the configuration is necessary for implementing a persistent hostname in holo-cli. Closes #20 Signed-off-by: Renato Westphal --- Cargo.toml | 1 + README.md | 1 + holo-daemon/Cargo.toml | 3 + holo-daemon/src/northbound/core.rs | 14 +- holo-daemon/src/northbound/yang.rs | 3 + holo-system/Cargo.toml | 24 + holo-system/LICENSE | 19 + holo-system/src/ibus.rs | 38 + holo-system/src/lib.rs | 81 ++ holo-system/src/northbound/configuration.rs | 103 +++ holo-system/src/northbound/mod.rs | 32 + holo-system/src/northbound/state.rs | 69 ++ holo-tools/yang-coverage.sh | 3 +- holo-utils/src/ibus.rs | 4 + holo-yang/Cargo.toml | 2 +- .../ietf-system-holo-deviations.yang | 234 ++++++ .../ietf/iana-crypt-hash@2014-08-06.yang | 99 +++ .../modules/ietf/ietf-system@2014-08-06.yang | 711 ++++++++++++++++++ holo-yang/src/lib.rs | 7 + 19 files changed, 1445 insertions(+), 3 deletions(-) create mode 100644 holo-system/Cargo.toml create mode 100644 holo-system/LICENSE create mode 100644 holo-system/src/ibus.rs create mode 100644 holo-system/src/lib.rs create mode 100644 holo-system/src/northbound/configuration.rs create mode 100644 holo-system/src/northbound/mod.rs create mode 100644 holo-system/src/northbound/state.rs create mode 100644 holo-yang/modules/deviations/ietf-system-holo-deviations.yang create mode 100644 holo-yang/modules/ietf/iana-crypt-hash@2014-08-06.yang create mode 100644 holo-yang/modules/ietf/ietf-system@2014-08-06.yang diff --git a/Cargo.toml b/Cargo.toml index 9c6736da..a00bbdc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "holo-protocol", "holo-rip", "holo-routing", + "holo-system", "holo-tools", "holo-utils", "holo-yang", diff --git a/README.md b/README.md index bbc14874..677079f2 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,7 @@ Holo supports the following IETF RFCs and Internet drafts: | ietf-routing@2018-03-13 | 100.00% | 85.71% | - | - | [92.31%](http://westphal.com.br/holo/ietf-routing.html) | | ietf-segment-routing-mpls@2021-05-26 | 62.50% | 0.00% | - | 23.53% | [32.76%](http://westphal.com.br/holo/ietf-segment-routing-mpls.html) | | ietf-segment-routing@2021-05-26 | 100.00% | - | - | - | [100.00%](http://westphal.com.br/holo/ietf-segment-routing.html) | +| ietf-system@2014-08-06 | 26.67% | 60.00% | 0.00% | - | [38.24%](http://westphal.com.br/holo/ietf-system@2014-08-06.coverage.md) | ## Funding diff --git a/holo-daemon/Cargo.toml b/holo-daemon/Cargo.toml index b49adc4b..ff1e6ca5 100644 --- a/holo-daemon/Cargo.toml +++ b/holo-daemon/Cargo.toml @@ -41,6 +41,7 @@ holo-policy = { path = "../holo-policy", optional = true } holo-protocol = { path = "../holo-protocol" } holo-rip = { path = "../holo-rip", optional = true } holo-routing = { path = "../holo-routing", optional = true } +holo-system = { path = "../holo-system", optional = true } holo-utils = { path = "../holo-utils" } holo-yang = { path = "../holo-yang" } @@ -61,6 +62,7 @@ default = [ "keychain", "policy", "routing", + "system", # Protocols "bfd", "bgp", @@ -74,6 +76,7 @@ interface = ["dep:holo-interface"] keychain = ["dep:holo-keychain"] policy = ["dep:holo-policy", "dep:holo-routing"] routing = ["dep:holo-routing", "dep:holo-interface"] +system = ["dep:holo-system"] # Protocols bfd = ["dep:holo-bfd", "holo-routing/bfd"] diff --git a/holo-daemon/src/northbound/core.rs b/holo-daemon/src/northbound/core.rs index 228b3ae1..24dfa9da 100644 --- a/holo-daemon/src/northbound/core.rs +++ b/holo-daemon/src/northbound/core.rs @@ -638,7 +638,8 @@ fn start_providers( let ibus_rx_routing = ibus_tx.subscribe(); let ibus_rx_interface = ibus_tx.subscribe(); let ibus_rx_keychain = ibus_tx.subscribe(); - let ibus_rx_policy = ibus_rx; + let ibus_rx_policy = ibus_tx.subscribe(); + let ibus_rx_system = ibus_rx; // Start holo-interface. #[cfg(feature = "interface")] @@ -673,6 +674,17 @@ fn start_providers( providers.push(daemon_tx); } + // Start holo-system. + #[cfg(feature = "system")] + { + let daemon_tx = holo_system::start( + provider_tx.clone(), + ibus_tx.clone(), + ibus_rx_system, + ); + providers.push(daemon_tx); + } + // Start holo-routing. #[cfg(feature = "routing")] { diff --git a/holo-daemon/src/northbound/yang.rs b/holo-daemon/src/northbound/yang.rs index d16a691f..9d6577e4 100644 --- a/holo-daemon/src/northbound/yang.rs +++ b/holo-daemon/src/northbound/yang.rs @@ -38,6 +38,9 @@ pub(crate) fn create_context() { #[cfg(feature = "policy")] modules_add::(&mut modules); + #[cfg(feature = "system")] + modules_add::(&mut modules); + // Add protocol modules based on enabled features. #[cfg(feature = "bfd")] { diff --git a/holo-system/Cargo.toml b/holo-system/Cargo.toml new file mode 100644 index 00000000..d96dfe8a --- /dev/null +++ b/holo-system/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "holo-system" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true + +[dependencies] +sysinfo = "0.30" + +async-trait.workspace = true +capctl.workspace = true +chrono.workspace = true +derive-new.workspace = true +tokio.workspace = true +tracing.workspace = true +yang3.workspace = true + +holo-northbound = { path = "../holo-northbound" } +holo-utils = { path = "../holo-utils" } +holo-yang = { path = "../holo-yang" } + +[lints] +workspace = true diff --git a/holo-system/LICENSE b/holo-system/LICENSE new file mode 100644 index 00000000..4481fc10 --- /dev/null +++ b/holo-system/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2023 The Holo Core Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/holo-system/src/ibus.rs b/holo-system/src/ibus.rs new file mode 100644 index 00000000..622b3c05 --- /dev/null +++ b/holo-system/src/ibus.rs @@ -0,0 +1,38 @@ +// +// Copyright (c) The Holo Core Contributors +// +// SPDX-License-Identifier: MIT +// + +use holo_utils::ibus::{IbusMsg, IbusSender}; + +use crate::Master; + +// ===== global functions ===== + +pub(crate) fn process_msg(master: &mut Master, msg: IbusMsg) { + match msg { + IbusMsg::HostnameQuery => { + notify_hostname_update( + &master.ibus_tx, + master.config.hostname.clone(), + ); + } + // Ignore other events. + _ => {} + } +} + +pub(crate) fn notify_hostname_update( + ibus_tx: &IbusSender, + hostname: Option, +) { + let msg = IbusMsg::HostnameUpdate(hostname); + notify(ibus_tx, msg); +} + +// ===== helper functions ===== + +fn notify(ibus_tx: &IbusSender, msg: IbusMsg) { + let _ = ibus_tx.send(msg); +} diff --git a/holo-system/src/lib.rs b/holo-system/src/lib.rs new file mode 100644 index 00000000..4c84d04c --- /dev/null +++ b/holo-system/src/lib.rs @@ -0,0 +1,81 @@ +// +// Copyright (c) The Holo Core Contributors +// +// SPDX-License-Identifier: MIT +// + +#![feature(let_chains)] + +mod ibus; +pub mod northbound; + +use holo_northbound::{ + process_northbound_msg, NbDaemonReceiver, NbDaemonSender, NbProviderSender, + ProviderBase, +}; +use holo_utils::ibus::{IbusReceiver, IbusSender}; +use northbound::configuration::SystemCfg; +use tokio::sync::mpsc; +use tracing::Instrument; + +#[derive(Debug)] +pub struct Master { + // Northbound Tx channel. + pub nb_tx: NbProviderSender, + // Internal bus Tx channel. + pub ibus_tx: IbusSender, + // System configuration. + pub config: SystemCfg, +} + +// ===== impl Master ===== + +impl Master { + async fn run( + &mut self, + mut nb_rx: NbDaemonReceiver, + mut ibus_rx: IbusReceiver, + ) { + let mut resources = vec![]; + + loop { + tokio::select! { + Some(request) = nb_rx.recv() => { + process_northbound_msg( + self, + &mut resources, + request, + ) + .await; + } + Ok(msg) = ibus_rx.recv() => { + ibus::process_msg(self, msg); + } + } + } + } +} + +// ===== global functions ===== + +pub fn start( + nb_tx: NbProviderSender, + ibus_tx: IbusSender, + ibus_rx: IbusReceiver, +) -> NbDaemonSender { + let (nb_daemon_tx, nb_daemon_rx) = mpsc::channel(4); + + tokio::spawn(async move { + let mut master = Master { + nb_tx, + ibus_tx, + config: Default::default(), + }; + + // Run task main loop. + let span = Master::debug_span(""); + master.run(nb_daemon_rx, ibus_rx).instrument(span).await; + }); + + nb_daemon_tx +} diff --git a/holo-system/src/northbound/configuration.rs b/holo-system/src/northbound/configuration.rs new file mode 100644 index 00000000..dc3d13d7 --- /dev/null +++ b/holo-system/src/northbound/configuration.rs @@ -0,0 +1,103 @@ +// +// Copyright (c) The Holo Core Contributors +// +// SPDX-License-Identifier: MIT +// + +use std::sync::LazyLock as Lazy; + +use async_trait::async_trait; +use holo_northbound::configuration::{ + self, Callbacks, CallbacksBuilder, Provider, +}; +use holo_northbound::yang::system; +use holo_utils::yang::DataNodeRefExt; + +use crate::{ibus, Master}; + +static CALLBACKS: Lazy> = + Lazy::new(load_callbacks); + +#[derive(Debug, Default)] +pub enum ListEntry { + #[default] + None, +} + +#[derive(Debug)] +pub enum Resource {} + +#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum Event { + HostnameChange, +} + +// ===== configuration structs ===== + +#[derive(Debug, Default)] +pub struct SystemCfg { + pub contact: Option, + pub hostname: Option, + pub location: Option, +} + +// ===== callbacks ===== + +fn load_callbacks() -> Callbacks { + CallbacksBuilder::::default() + .path(system::contact::PATH) + .modify_apply(|master, args| { + let contact = args.dnode.get_string(); + master.config.contact = Some(contact); + }) + .delete_apply(|master, _args| { + master.config.contact = None; + }) + .path(system::hostname::PATH) + .modify_apply(|master, args| { + let hostname = args.dnode.get_string(); + master.config.hostname = Some(hostname); + + let event_queue = args.event_queue; + event_queue.insert(Event::HostnameChange); + }) + .delete_apply(|master, args| { + master.config.hostname = None; + + let event_queue = args.event_queue; + event_queue.insert(Event::HostnameChange); + }) + .path(system::location::PATH) + .modify_apply(|master, args| { + let location = args.dnode.get_string(); + master.config.location = Some(location); + }) + .delete_apply(|master, _args| { + master.config.location = None; + }) + .build() +} + +// ===== impl Master ===== + +#[async_trait] +impl Provider for Master { + type ListEntry = ListEntry; + type Event = Event; + type Resource = Resource; + + fn callbacks() -> Option<&'static Callbacks> { + Some(&CALLBACKS) + } + + async fn process_event(&mut self, event: Event) { + match event { + Event::HostnameChange => { + ibus::notify_hostname_update( + &self.ibus_tx, + self.config.hostname.clone(), + ); + } + } + } +} diff --git a/holo-system/src/northbound/mod.rs b/holo-system/src/northbound/mod.rs new file mode 100644 index 00000000..186dc898 --- /dev/null +++ b/holo-system/src/northbound/mod.rs @@ -0,0 +1,32 @@ +// +// Copyright (c) The Holo Core Contributors +// +// SPDX-License-Identifier: MIT +// + +pub mod configuration; +pub mod state; + +use holo_northbound::{rpc, ProviderBase}; +use tracing::{debug_span, Span}; + +use crate::Master; + +// ===== impl Master ===== + +impl ProviderBase for Master { + fn yang_modules() -> &'static [&'static str] { + &["ietf-system"] + } + + fn top_level_node(&self) -> String { + "/ietf-system:system".to_owned() + } + + fn debug_span(_name: &str) -> Span { + debug_span!("system") + } +} + +// No RPC/Actions to implement. +impl rpc::Provider for Master {} diff --git a/holo-system/src/northbound/state.rs b/holo-system/src/northbound/state.rs new file mode 100644 index 00000000..052f3d6f --- /dev/null +++ b/holo-system/src/northbound/state.rs @@ -0,0 +1,69 @@ +// +// Copyright (c) The Holo Core Contributors +// +// SPDX-License-Identifier: MIT +// + +use std::borrow::Cow; +use std::sync::LazyLock as Lazy; + +use chrono::{DateTime, Utc}; +use holo_northbound::state::{ + Callbacks, CallbacksBuilder, ListEntryKind, Provider, +}; +use holo_northbound::yang::system_state; +use sysinfo::System; + +use crate::Master; + +pub static CALLBACKS: Lazy> = Lazy::new(load_callbacks); + +#[derive(Debug, Default)] +pub enum ListEntry { + #[default] + None, +} + +// ===== callbacks ===== + +fn load_callbacks() -> Callbacks { + CallbacksBuilder::::default() + .path(system_state::platform::PATH) + .get_object(|_context, _args| { + use system_state::platform::Platform; + Box::new(Platform { + os_name: System::name().map(Cow::Owned), + os_release: System::kernel_version().map(Cow::Owned), + os_version: System::os_version().map(Cow::Owned), + machine: System::cpu_arch().map(Cow::Owned), + }) + }) + .path(system_state::clock::PATH) + .get_object(|_context, _args| { + use system_state::clock::Clock; + let time_now = Utc::now(); + let time_boot = + DateTime::from_timestamp(System::boot_time() as i64, 0); + Box::new(Clock { + current_datetime: Some(Cow::Owned(time_now)), + boot_datetime: time_boot.map(Cow::Owned), + }) + }) + .build() +} + +// ===== impl Master ===== + +impl Provider for Master { + const STATE_PATH: &'static str = "/ietf-system:system-state"; + + type ListEntry<'a> = ListEntry; + + fn callbacks() -> Option<&'static Callbacks> { + Some(&CALLBACKS) + } +} + +// ===== impl ListEntry ===== + +impl ListEntryKind for ListEntry {} diff --git a/holo-tools/yang-coverage.sh b/holo-tools/yang-coverage.sh index 446bd24b..3cf60949 100755 --- a/holo-tools/yang-coverage.sh +++ b/holo-tools/yang-coverage.sh @@ -22,4 +22,5 @@ cargo run --bin yang_coverage --\ -m ietf-ospf\ -m ietf-ospf-sr-mpls\ -m ietf-ospfv3-extended-lsa\ - -m ietf-rip + -m ietf-rip\ + -m ietf-system diff --git a/holo-utils/src/ibus.rs b/holo-utils/src/ibus.rs index 49b7e013..389b06bd 100644 --- a/holo-utils/src/ibus.rs +++ b/holo-utils/src/ibus.rs @@ -44,6 +44,10 @@ pub enum IbusMsg { sess_key: bfd::SessionKey, state: bfd::State, }, + // Query the current hostname. + HostnameQuery, + // Hostname update notification. + HostnameUpdate(Option), // Request to dump information about all interfaces. InterfaceDump, // Query information about a specific interface. diff --git a/holo-yang/Cargo.toml b/holo-yang/Cargo.toml index 29fdce3d..c853e57c 100644 --- a/holo-yang/Cargo.toml +++ b/holo-yang/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "holo-yang" -version = "0.5.0" +version = "0.5.1" authors.workspace = true license.workspace = true edition.workspace = true diff --git a/holo-yang/modules/deviations/ietf-system-holo-deviations.yang b/holo-yang/modules/deviations/ietf-system-holo-deviations.yang new file mode 100644 index 00000000..0bc13fa5 --- /dev/null +++ b/holo-yang/modules/deviations/ietf-system-holo-deviations.yang @@ -0,0 +1,234 @@ +module ietf-system-holo-deviations { + yang-version 1.1; + namespace "http://holo-routing.org/yang/ietf-system-holo-deviations"; + prefix ietf-system-holo-deviations; + + import ietf-system { + prefix sys; + } + + organization + "Holo Routing Stack"; + + description + "This module defines deviation statements for the ietf-system + module."; + + /* + deviation "/sys:system" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:contact" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:hostname" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:location" { + deviate not-supported; + } + */ + + deviation "/sys:system/sys:clock" { + deviate not-supported; + } + + /* + deviation "/sys:system/sys:clock/sys:timezone" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-utc-offset" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-utc-offset/sys:timezone-utc-offset" { + deviate not-supported; + } + */ + + deviation "/sys:system/sys:dns-resolver" { + deviate not-supported; + } + + /* + deviation "/sys:system/sys:dns-resolver/sys:search" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:server" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:server/sys:name" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:server/sys:transport" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:server/sys:transport/sys:udp-and-tcp" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:server/sys:transport/sys:udp-and-tcp/sys:udp-and-tcp" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:server/sys:transport/sys:udp-and-tcp/sys:udp-and-tcp/sys:address" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:options" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:options/sys:timeout" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system/sys:dns-resolver/sys:options/sys:attempts" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state/sys:platform" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state/sys:platform/sys:os-name" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state/sys:platform/sys:os-release" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state/sys:platform/sys:os-version" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state/sys:platform/sys:machine" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state/sys:clock" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state/sys:clock/sys:current-datetime" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-state/sys:clock/sys:boot-datetime" { + deviate not-supported; + } + */ + + deviation "/sys:set-current-datetime" { + deviate not-supported; + } + + /* + deviation "/sys:set-current-datetime/sys:input" { + deviate not-supported; + } + */ + + /* + deviation "/sys:set-current-datetime/sys:input/sys:current-datetime" { + deviate not-supported; + } + */ + + /* + deviation "/sys:set-current-datetime/sys:output" { + deviate not-supported; + } + */ + + deviation "/sys:system-restart" { + deviate not-supported; + } + + /* + deviation "/sys:system-restart/sys:input" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-restart/sys:output" { + deviate not-supported; + } + */ + + deviation "/sys:system-shutdown" { + deviate not-supported; + } + + /* + deviation "/sys:system-shutdown/sys:input" { + deviate not-supported; + } + */ + + /* + deviation "/sys:system-shutdown/sys:output" { + deviate not-supported; + } + */ +} diff --git a/holo-yang/modules/ietf/iana-crypt-hash@2014-08-06.yang b/holo-yang/modules/ietf/iana-crypt-hash@2014-08-06.yang new file mode 100644 index 00000000..fc4544a8 --- /dev/null +++ b/holo-yang/modules/ietf/iana-crypt-hash@2014-08-06.yang @@ -0,0 +1,99 @@ +module iana-crypt-hash { + namespace "urn:ietf:params:xml:ns:yang:iana-crypt-hash"; + prefix ianach; + organization "IANA"; + contact + " Internet Assigned Numbers Authority + Postal: ICANN + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States + Tel: +1 310 301 5800 + E-Mail: iana@iana.org>"; + description + "This YANG module defines a type for storing passwords + using a hash function and features to indicate which hash + functions are supported by an implementation. + The latest revision of this YANG module can be obtained from + the IANA web site. + Requests for new values should be made to IANA via + email (iana@iana.org). + Copyright (c) 2014 IETF Trust and the persons identified as + authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + The initial version of this YANG module is part of RFC 7317; + see the RFC itself for full legal notices."; + revision 2014-08-06 { + description + "Initial revision."; + reference + "RFC 7317: A YANG Data Model for System Management"; + } + typedef crypt-hash { + type string { + pattern + '$0$.*' + + '|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}' + + '|$5$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}' + + '|$6$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}'; + } + description + "The crypt-hash type is used to store passwords using + a hash function. The algorithms for applying the hash + function and encoding the result are implemented in + various UNIX systems as the function crypt(3). + A value of this type matches one of the forms: + $0$ + $$$ + $$$$ + The '$0$' prefix signals that the value is clear text. When + such a value is received by the server, a hash value is + calculated, and the string '$$$' or + $$$$ is prepended to the result. This + value is stored in the configuration data store. + If a value starting with '$$', where is not '0', is + received, the server knows that the value already represents a + hashed value and stores it 'as is' in the data store. + When a server needs to verify a password given by a user, it + finds the stored password hash string for that user, extracts + the salt, and calculates the hash with the salt and given + password as input. If the calculated hash value is the same + as the stored value, the password given by the client is + accepted. + This type defines the following hash functions: + id | hash function | feature + ---+---------------+------------------- + 1 | MD5 | crypt-hash-md5 + 5 | SHA-256 | crypt-hash-sha-256 + 6 | SHA-512 | crypt-hash-sha-512 + The server indicates support for the different hash functions + by advertising the corresponding feature."; + reference + "IEEE Std 1003.1-2008 - crypt() function + RFC 1321: The MD5 Message-Digest Algorithm + FIPS.180-4.2012: Secure Hash Standard (SHS)"; + } + feature crypt-hash-md5 { + description + "Indicates that the device supports the MD5 + hash function in 'crypt-hash' values."; + reference "RFC 1321: The MD5 Message-Digest Algorithm"; + } + feature crypt-hash-sha-256 { + description + "Indicates that the device supports the SHA-256 + hash function in 'crypt-hash' values."; + reference "FIPS.180-4.2012: Secure Hash Standard (SHS)"; + } + feature crypt-hash-sha-512 { + description + "Indicates that the device supports the SHA-512 + hash function in 'crypt-hash' values."; + reference "FIPS.180-4.2012: Secure Hash Standard (SHS)"; + } +} diff --git a/holo-yang/modules/ietf/ietf-system@2014-08-06.yang b/holo-yang/modules/ietf/ietf-system@2014-08-06.yang new file mode 100644 index 00000000..a8d9e089 --- /dev/null +++ b/holo-yang/modules/ietf/ietf-system@2014-08-06.yang @@ -0,0 +1,711 @@ +module ietf-system { + namespace "urn:ietf:params:xml:ns:yang:ietf-system"; + prefix "sys"; + import ietf-yang-types { + prefix yang; + } + import ietf-inet-types { + prefix inet; + } + import ietf-netconf-acm { + prefix nacm; + } + import iana-crypt-hash { + prefix ianach; + } + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + contact + "WG Web: + WG List: + WG Chair: Thomas Nadeau + + WG Chair: Juergen Schoenwaelder + + Editor: Andy Bierman + + Editor: Martin Bjorklund + "; + description + "This module contains a collection of YANG definitions for the + configuration and identification of some common system + properties within a device containing a NETCONF server. This + includes data node definitions for system identification, + time-of-day management, user management, DNS resolver + configuration, and some protocol operations for system + management. + Copyright (c) 2014 IETF Trust and the persons identified as + authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 7317; see + the RFC itself for full legal notices."; + revision 2014-08-06 { + description + "Initial revision."; + reference + "RFC 7317: A YANG Data Model for System Management"; + } + /* + * Typedefs + */ + typedef timezone-name { + type string; + description + "A time zone name as used by the Time Zone Database, + sometimes referred to as the 'Olson Database'. + The exact set of valid values is an implementation-specific + matter. Client discovery of the exact set of time zone names + for a particular server is out of scope."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + /* + * Features + */ + feature radius { + description + "Indicates that the device can be configured as a RADIUS + client."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + feature authentication { + description + "Indicates that the device supports configuration of + user authentication."; + } + feature local-users { + if-feature authentication; + description + "Indicates that the device supports configuration of + local user authentication."; + } + feature radius-authentication { + if-feature radius; + if-feature authentication; + description + "Indicates that the device supports configuration of user + authentication over RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + feature ntp { + description + "Indicates that the device can be configured to use one or + more NTP servers to set the system date and time."; + } + feature ntp-udp-port { + if-feature ntp; + description + "Indicates that the device supports the configuration of + the UDP port for NTP servers. + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + feature timezone-name { + description + "Indicates that the local time zone on the device + can be configured to use the TZ database + to set the time zone and manage daylight saving time."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + feature dns-udp-tcp-port { + description + "Indicates that the device supports the configuration of + the UDP and TCP port for DNS servers. + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + /* + * Identities + */ + identity authentication-method { + description + "Base identity for user authentication methods."; + } + identity radius { + base authentication-method; + description + "Indicates user authentication using RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + identity local-users { + base authentication-method; + description + "Indicates password-based authentication of locally + configured users."; + } + identity radius-authentication-type { + description + "Base identity for RADIUS authentication types."; + } + identity radius-pap { + base radius-authentication-type; + description + "The device requests Password Authentication Protocol (PAP) + authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + identity radius-chap { + base radius-authentication-type; + description + "The device requests Challenge Handshake Authentication + Protocol (CHAP) authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + /* + * Configuration data nodes + */ + container system { + description + "System group configuration."; + leaf contact { + type string; + description + "The administrator contact information for the system. + A server implementation MAY map this leaf to the sysContact + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysContact. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysContact"; + } + leaf hostname { + type inet:domain-name; + description + "The name of the host. This name can be a single domain + label or the fully qualified domain name of the host."; + } + leaf location { + type string; + description + "The system location. + A server implementation MAY map this leaf to the sysLocation + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysLocation. The definition + of such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysLocation"; + } + container clock { + description + "Configuration of the system date and time properties."; + choice timezone { + description + "The system time zone information."; + case timezone-name { + if-feature timezone-name; + leaf timezone-name { + type timezone-name; + description + "The TZ database name to use for the system, such + as 'Europe/Stockholm'."; + } + } + case timezone-utc-offset { + leaf timezone-utc-offset { + type int16 { + range "-1500 .. 1500"; + } + units "minutes"; + description + "The number of minutes to add to UTC time to + identify the time zone for this system. For example, + 'UTC - 8:00 hours' would be represented as '-480'. + Note that automatic daylight saving time adjustment + is not provided if this object is used."; + } + } + } + } + container ntp { + if-feature ntp; + presence + "Enables the NTP client unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Configuration of the NTP client."; + leaf enabled { + type boolean; + default true; + description + "Indicates that the system should attempt to + synchronize the system clock with an NTP server + from the 'ntp/server' list."; + } + list server { + key name; + description + "List of NTP servers to use for system clock + synchronization. If '/system/ntp/enabled' + is 'true', then the system will attempt to + contact and utilize the specified NTP servers."; + leaf name { + type string; + description + "An arbitrary name for the NTP server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for NTP."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the NTP server."; + } + leaf port { + if-feature ntp-udp-port; + type inet:port-number; + default 123; + description + "The port number of the NTP server."; + } + } + } + } + leaf association-type { + type enumeration { + enum server { + description + "Use client association mode. This device + will not provide synchronization to the + configured NTP server."; + } + enum peer { + description + "Use symmetric active association mode. + This device may provide synchronization + to the configured NTP server."; + } + enum pool { + description + "Use client association mode with one or + more of the NTP servers found by DNS + resolution of the domain name given by + the 'address' leaf. This device will not + provide synchronization to the servers."; + } + } + default server; + description + "The desired association type for this NTP server."; + } + leaf iburst { + type boolean; + default false; + description + "Indicates whether this server should enable burst + synchronization or not."; + } + leaf prefer { + type boolean; + default false; + description + "Indicates whether this server should be preferred + or not."; + } + } + } + container dns-resolver { + description + "Configuration of the DNS resolver."; + leaf-list search { + type inet:domain-name; + ordered-by user; + description + "An ordered list of domains to search when resolving + a host name."; + } + list server { + key name; + ordered-by user; + description + "List of the DNS servers that the resolver should query. + When the resolver is invoked by a calling application, it + sends the query to the first name server in this list. If + no response has been received within 'timeout' seconds, + the resolver continues with the next server in the list. + If no response is received from any server, the resolver + continues with the first server again. When the resolver + has traversed the list 'attempts' times without receiving + any response, it gives up and returns an error to the + calling application. + Implementations MAY limit the number of entries in this + list."; + leaf name { + type string; + description + "An arbitrary name for the DNS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + case udp-and-tcp { + container udp-and-tcp { + description + "Contains UDP- and TCP-specific configuration + parameters for DNS."; + reference + "RFC 1035: Domain Names - Implementation and + Specification + RFC 5966: DNS Transport over TCP - Implementation + Requirements"; + leaf address { + type inet:ip-address; + mandatory true; + description + "The address of the DNS server."; + } + leaf port { + if-feature dns-udp-tcp-port; + type inet:port-number; + default 53; + description + "The UDP and TCP port number of the DNS server."; + } + } + } + } + } + container options { + description + "Resolver options. The set of available options has been + limited to those that are generally available across + different resolver implementations and generally useful."; + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The amount of time the resolver will wait for a + response from each remote name server before + retrying the query via a different name server."; + } + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the resolver will send a query to + all of its name servers before giving up and returning + an error to the calling application."; + } + } + } + container radius { + if-feature radius; + description + "Configuration of the RADIUS client."; + list server { + key name; + ordered-by user; + description + "List of RADIUS servers used by the device. + When the RADIUS client is invoked by a calling + application, it sends the query to the first server in + this list. If no response has been received within + 'timeout' seconds, the client continues with the next + server in the list. If no response is received from any + server, the client continues with the first server again. + When the client has traversed the list 'attempts' times + without receiving any response, it gives up and returns an + error to the calling application."; + leaf name { + type string; + description + "An arbitrary name for the RADIUS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for RADIUS."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the RADIUS server."; + } + leaf authentication-port { + type inet:port-number; + default "1812"; + description + "The port number of the RADIUS server."; + } + leaf shared-secret { + type string; + mandatory true; + nacm:default-deny-all; + description + "The shared secret, which is known to both the + RADIUS client and server."; + reference + "RFC 2865: Remote Authentication Dial In User + Service (RADIUS)"; + } + } + } + } + leaf authentication-type { + type identityref { + base radius-authentication-type; + } + default radius-pap; + description + "The authentication type requested from the RADIUS + server."; + } + } + container options { + description + "RADIUS client options."; + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The number of seconds the device will wait for a + response from each RADIUS server before trying with a + different server."; + } + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the device will send a query to + all of its RADIUS servers before giving up."; + } + } + } + container authentication { + nacm:default-deny-write; + if-feature authentication; + description + "The authentication configuration subtree."; + leaf-list user-authentication-order { + type identityref { + base authentication-method; + } + must '(. != "sys:radius" or ../../radius/server)' { + error-message + "When 'radius' is used, a RADIUS server" + + " must be configured."; + description + "When 'radius' is used as an authentication method, + a RADIUS server must be configured."; + } + ordered-by user; + description + "When the device authenticates a user with a password, + it tries the authentication methods in this leaf-list in + order. If authentication with one method fails, the next + method is used. If no method succeeds, the user is + denied access. + An empty user-authentication-order leaf-list still allows + authentication of users using mechanisms that do not + involve a password. + If the 'radius-authentication' feature is advertised by + the NETCONF server, the 'radius' identity can be added to + this list. + If the 'local-users' feature is advertised by the + NETCONF server, the 'local-users' identity can be + added to this list."; + } + list user { + if-feature local-users; + key name; + description + "The list of local users configured on this device."; + leaf name { + type string; + description + "The user name string identifying this entry."; + } + leaf password { + type ianach:crypt-hash; + description + "The password for this entry."; + } + list authorized-key { + key name; + description + "A list of public SSH keys for this user. These keys + are allowed for SSH authentication, as described in + RFC 4253."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + leaf name { + type string; + description + "An arbitrary name for the SSH key."; + } + leaf algorithm { + type string; + mandatory true; + description + "The public key algorithm name for this SSH key. + Valid values are the values in the IANA 'Secure Shell + (SSH) Protocol Parameters' registry, Public Key + Algorithm Names."; + reference + "IANA 'Secure Shell (SSH) Protocol Parameters' + registry, Public Key Algorithm Names"; + } + leaf key-data { + type binary; + mandatory true; + description + "The binary public key data for this SSH key, as + specified by RFC 4253, Section 6.6, i.e.: + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + } + } + } + } + } + /* + * Operational state data nodes + */ + container system-state { + config false; + description + "System group operational state."; + container platform { + description + "Contains vendor-specific information for + identifying the system platform and operating system."; + reference + "IEEE Std 1003.1-2008 - sys/utsname.h"; + leaf os-name { + type string; + description + "The name of the operating system in use - + for example, 'Linux'."; + reference + "IEEE Std 1003.1-2008 - utsname.sysname"; + } + leaf os-release { + type string; + description + "The current release level of the operating + system in use. This string MAY indicate + the OS source code revision."; + reference + "IEEE Std 1003.1-2008 - utsname.release"; + } + leaf os-version { + type string; + description + "The current version level of the operating + system in use. This string MAY indicate + the specific OS build date and target variant + information."; + reference + "IEEE Std 1003.1-2008 - utsname.version"; + } + leaf machine { + type string; + description + "A vendor-specific identifier string representing + the hardware in use."; + reference + "IEEE Std 1003.1-2008 - utsname.machine"; + } + } + container clock { + description + "Monitoring of the system date and time properties."; + leaf current-datetime { + type yang:date-and-time; + description + "The current system date and time."; + } + leaf boot-datetime { + type yang:date-and-time; + description + "The system date and time when the system last restarted."; + } + } + } + rpc set-current-datetime { + nacm:default-deny-all; + description + "Set the /system-state/clock/current-datetime leaf + to the specified value. + If the system is using NTP (i.e., /system/ntp/enabled + is set to 'true'), then this operation will fail with + error-tag 'operation-failed' and error-app-tag value of + 'ntp-active'."; + input { + leaf current-datetime { + type yang:date-and-time; + mandatory true; + description + "The current system date and time."; + } + } + } + rpc system-restart { + nacm:default-deny-all; + description + "Request that the entire system be restarted immediately. + A server SHOULD send an rpc reply to the client before + restarting the system."; + } + rpc system-shutdown { + nacm:default-deny-all; + description + "Request that the entire system be shut down immediately. + A server SHOULD send an rpc reply to the client before + shutting down the system."; + } +} diff --git a/holo-yang/src/lib.rs b/holo-yang/src/lib.rs index 7e1d1a92..b433482e 100644 --- a/holo-yang/src/lib.rs +++ b/holo-yang/src/lib.rs @@ -39,6 +39,8 @@ pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { include_str!("../modules/ietf/iana-bgp-rib-types@2023-07-05.yang"), EmbeddedModuleKey::new("iana-bgp-types", Some("2023-07-05"), None, None) => include_str!("../modules/ietf/iana-bgp-types@2023-07-05.yang"), + EmbeddedModuleKey::new("iana-crypt-hash", Some("2014-08-06"), None, None) => + include_str!("../modules/ietf/iana-crypt-hash@2014-08-06.yang"), EmbeddedModuleKey::new("iana-if-type", Some("2017-01-19"), None, None) => include_str!("../modules/ietf/iana-if-type@2017-01-19.yang"), EmbeddedModuleKey::new("iana-routing-types", Some("2018-10-29"), None, None) => @@ -103,6 +105,8 @@ pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { include_str!("../modules/ietf/ietf-ospfv3-extended-lsa@2024-06-07.yang"), EmbeddedModuleKey::new("ietf-rip", Some("2020-02-20"), None, None) => include_str!("../modules/ietf/ietf-rip@2020-02-20.yang"), + EmbeddedModuleKey::new("ietf-system", Some("2014-08-06"), None, None) => + include_str!("../modules/ietf/ietf-system@2014-08-06.yang"), EmbeddedModuleKey::new("ietf-routing", Some("2018-03-13"), None, None) => include_str!("../modules/ietf/ietf-routing@2018-03-13.yang"), EmbeddedModuleKey::new("ietf-routing-policy", Some("2021-10-11"), None, None) => @@ -151,6 +155,8 @@ pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { include_str!("../modules/deviations/ietf-ospfv3-extended-lsa-holo-deviations.yang"), EmbeddedModuleKey::new("ietf-rip-holo-deviations", None, None, None) => include_str!("../modules/deviations/ietf-rip-holo-deviations.yang"), + EmbeddedModuleKey::new("ietf-system-holo-deviations", None, None, None) => + include_str!("../modules/deviations/ietf-system-holo-deviations.yang"), EmbeddedModuleKey::new("ietf-routing-holo-deviations", None, None, None) => include_str!("../modules/deviations/ietf-routing-holo-deviations.yang"), EmbeddedModuleKey::new("ietf-ipv6-unicast-routing-holo-deviations", None, None, None) => @@ -201,6 +207,7 @@ pub static YANG_IMPLEMENTED_MODULES: Lazy> = "ietf-ospf-sr-mpls", "ietf-ospfv3-extended-lsa", "ietf-rip", + "ietf-system", "ietf-tcp", // IETF Holo augmentations "holo-bgp", From 32a0313bbc7010307dd5a72adfd25cd475283f8a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 9 Jul 2024 21:20:37 -0300 Subject: [PATCH 12/14] yang: rename deviation modules to follow industry convention Rename from ietf-XXX-holo-deviations to holo-ietf-XXX-deviations. Apparently this is the naming convention most vendors are following. Signed-off-by: Renato Westphal --- holo-tools/src/yang_deviations.rs | 6 +- holo-yang/Cargo.toml | 2 +- ...ons.yang => holo-ietf-bgp-deviations.yang} | 6 +- ...> holo-ietf-if-extensions-deviations.yang} | 6 +- ...etf-if-vlan-encapsulation-deviations.yang} | 6 +- ...g => holo-ietf-interfaces-deviations.yang} | 6 +- ...ions.yang => holo-ietf-ip-deviations.yang} | 6 +- ...ietf-ipv6-unicast-routing-deviations.yang} | 6 +- ...ng => holo-ietf-key-chain-deviations.yang} | 6 +- ...ns.yang => holo-ietf-mpls-deviations.yang} | 6 +- ...ang => holo-ietf-mpls-ldp-deviations.yang} | 6 +- ...ns.yang => holo-ietf-ospf-deviations.yang} | 6 +- ...=> holo-ietf-ospf-sr-mpls-deviations.yang} | 6 +- ...-ietf-ospfv3-extended-lsa-deviations.yang} | 6 +- ...ons.yang => holo-ietf-rip-deviations.yang} | 6 +- ...yang => holo-ietf-routing-deviations.yang} | 6 +- ... holo-ietf-routing-policy-deviations.yang} | 6 +- ...ietf-segment-routing-mpls-deviations.yang} | 6 +- ....yang => holo-ietf-system-deviations.yang} | 6 +- holo-yang/src/lib.rs | 70 +++++++++---------- 20 files changed, 90 insertions(+), 90 deletions(-) rename holo-yang/modules/deviations/{ietf-bgp-holo-deviations.yang => holo-ietf-bgp-deviations.yang} (99%) rename holo-yang/modules/deviations/{ietf-if-extensions-holo-deviations.yang => holo-ietf-if-extensions-deviations.yang} (74%) rename holo-yang/modules/deviations/{ietf-if-vlan-encapsulation-holo-deviations.yang => holo-ietf-if-vlan-encapsulation-deviations.yang} (87%) rename holo-yang/modules/deviations/{ietf-interfaces-holo-deviations.yang => holo-ietf-interfaces-deviations.yang} (86%) rename holo-yang/modules/deviations/{ietf-ip-holo-deviations.yang => holo-ietf-ip-deviations.yang} (94%) rename holo-yang/modules/deviations/{ietf-ipv6-unicast-routing-holo-deviations.yang => holo-ietf-ipv6-unicast-routing-deviations.yang} (95%) rename holo-yang/modules/deviations/{ietf-key-chain-holo-deviations.yang => holo-ietf-key-chain-deviations.yang} (97%) rename holo-yang/modules/deviations/{ietf-mpls-holo-deviations.yang => holo-ietf-mpls-deviations.yang} (96%) rename holo-yang/modules/deviations/{ietf-mpls-ldp-holo-deviations.yang => holo-ietf-mpls-ldp-deviations.yang} (96%) rename holo-yang/modules/deviations/{ietf-ospf-holo-deviations.yang => holo-ietf-ospf-deviations.yang} (99%) rename holo-yang/modules/deviations/{ietf-ospf-sr-mpls-holo-deviations.yang => holo-ietf-ospf-sr-mpls-deviations.yang} (99%) rename holo-yang/modules/deviations/{ietf-ospfv3-extended-lsa-holo-deviations.yang => holo-ietf-ospfv3-extended-lsa-deviations.yang} (98%) rename holo-yang/modules/deviations/{ietf-rip-holo-deviations.yang => holo-ietf-rip-deviations.yang} (98%) rename holo-yang/modules/deviations/{ietf-routing-holo-deviations.yang => holo-ietf-routing-deviations.yang} (75%) rename holo-yang/modules/deviations/{ietf-routing-policy-holo-deviations.yang => holo-ietf-routing-policy-deviations.yang} (84%) rename holo-yang/modules/deviations/{ietf-segment-routing-mpls-holo-deviations.yang => holo-ietf-segment-routing-mpls-deviations.yang} (97%) rename holo-yang/modules/deviations/{ietf-system-holo-deviations.yang => holo-ietf-system-deviations.yang} (96%) diff --git a/holo-tools/src/yang_deviations.rs b/holo-tools/src/yang_deviations.rs index 55bfc5a3..15edf1aa 100644 --- a/holo-tools/src/yang_deviations.rs +++ b/holo-tools/src/yang_deviations.rs @@ -58,10 +58,10 @@ fn main() { // Header. println!( "\ - module {}-holo-deviations {{\ + module holo-{}-deviations {{\ \n yang-version 1.1;\ - \n namespace \"http://holo-routing.org/yang/{}-holo-deviations\";\ - \n prefix {}-holo-deviations;\ + \n namespace \"http://holo-routing.org/yang/holo-{}-deviations\";\ + \n prefix holo-{}-deviations;\ \n\ \n import {} {{\ \n prefix {};\ diff --git a/holo-yang/Cargo.toml b/holo-yang/Cargo.toml index c853e57c..fde09c92 100644 --- a/holo-yang/Cargo.toml +++ b/holo-yang/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "holo-yang" -version = "0.5.1" +version = "0.5.2" authors.workspace = true license.workspace = true edition.workspace = true diff --git a/holo-yang/modules/deviations/ietf-bgp-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-bgp-deviations.yang similarity index 99% rename from holo-yang/modules/deviations/ietf-bgp-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-bgp-deviations.yang index c54d4868..1c19ed8b 100644 --- a/holo-yang/modules/deviations/ietf-bgp-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-bgp-deviations.yang @@ -1,7 +1,7 @@ -module ietf-bgp-holo-deviations { +module holo-ietf-bgp-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-bgp-holo-deviations"; - prefix ietf-bgp-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-bgp-deviations"; + prefix holo-ietf-bgp-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-if-extensions-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-if-extensions-deviations.yang similarity index 74% rename from holo-yang/modules/deviations/ietf-if-extensions-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-if-extensions-deviations.yang index f598ee60..5c874952 100644 --- a/holo-yang/modules/deviations/ietf-if-extensions-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-if-extensions-deviations.yang @@ -1,7 +1,7 @@ -module ietf-if-extensions-holo-deviations { +module holo-ietf-if-extensions-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-if-extensions-holo-deviations"; - prefix ietf-if-extensions-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-if-extensions-deviations"; + prefix holo-ietf-if-extensions-deviations; import ietf-interfaces { prefix if; diff --git a/holo-yang/modules/deviations/ietf-if-vlan-encapsulation-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-if-vlan-encapsulation-deviations.yang similarity index 87% rename from holo-yang/modules/deviations/ietf-if-vlan-encapsulation-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-if-vlan-encapsulation-deviations.yang index cfaeb083..18391c50 100644 --- a/holo-yang/modules/deviations/ietf-if-vlan-encapsulation-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-if-vlan-encapsulation-deviations.yang @@ -1,7 +1,7 @@ -module ietf-if-vlan-encapsulation-holo-deviations { +module holo-ietf-if-vlan-encapsulation-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-if-vlan-encapsulation-holo-deviations"; - prefix ietf-if-vlan-encapsulation-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-if-vlan-encapsulation-deviations"; + prefix holo-ietf-if-vlan-encapsulation-deviations; import ietf-interfaces { prefix if; diff --git a/holo-yang/modules/deviations/ietf-interfaces-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-interfaces-deviations.yang similarity index 86% rename from holo-yang/modules/deviations/ietf-interfaces-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-interfaces-deviations.yang index 088b91f8..069e3f89 100644 --- a/holo-yang/modules/deviations/ietf-interfaces-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-interfaces-deviations.yang @@ -1,7 +1,7 @@ -module ietf-interfaces-holo-deviations { +module holo-ietf-interfaces-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-interfaces-holo-deviations"; - prefix ietf-interfaces-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-interfaces-deviations"; + prefix holo-ietf-interfaces-deviations; import ietf-interfaces { prefix if; diff --git a/holo-yang/modules/deviations/ietf-ip-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-ip-deviations.yang similarity index 94% rename from holo-yang/modules/deviations/ietf-ip-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-ip-deviations.yang index 9fd39817..16e3b859 100644 --- a/holo-yang/modules/deviations/ietf-ip-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-ip-deviations.yang @@ -1,7 +1,7 @@ -module ietf-ip-holo-deviations { +module holo-ietf-ip-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-ip-holo-deviations"; - prefix ietf-ip-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-ip-deviations"; + prefix holo-ietf-ip-deviations; import ietf-interfaces { prefix if; diff --git a/holo-yang/modules/deviations/ietf-ipv6-unicast-routing-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-ipv6-unicast-routing-deviations.yang similarity index 95% rename from holo-yang/modules/deviations/ietf-ipv6-unicast-routing-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-ipv6-unicast-routing-deviations.yang index abffeb1b..0d6451b9 100644 --- a/holo-yang/modules/deviations/ietf-ipv6-unicast-routing-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-ipv6-unicast-routing-deviations.yang @@ -1,7 +1,7 @@ -module ietf-ipv6-unicast-routing-holo-deviations { +module holo-ietf-ipv6-unicast-routing-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-ipv6-unicast-routing-holo-deviations"; - prefix ietf-ipv6-unicast-routing-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-ipv6-unicast-routing-deviations"; + prefix holo-ietf-ipv6-unicast-routing-deviations; import ietf-interfaces { prefix if; diff --git a/holo-yang/modules/deviations/ietf-key-chain-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-key-chain-deviations.yang similarity index 97% rename from holo-yang/modules/deviations/ietf-key-chain-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-key-chain-deviations.yang index a1dba067..34c48480 100644 --- a/holo-yang/modules/deviations/ietf-key-chain-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-key-chain-deviations.yang @@ -1,7 +1,7 @@ -module ietf-key-chain-holo-deviations { +module holo-ietf-key-chain-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-key-chain-holo-deviations"; - prefix ietf-key-chain-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-key-chain-deviations"; + prefix holo-ietf-key-chain-deviations; import ietf-key-chain { prefix key-chain; diff --git a/holo-yang/modules/deviations/ietf-mpls-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-mpls-deviations.yang similarity index 96% rename from holo-yang/modules/deviations/ietf-mpls-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-mpls-deviations.yang index e2e68c3d..63746326 100644 --- a/holo-yang/modules/deviations/ietf-mpls-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-mpls-deviations.yang @@ -1,7 +1,7 @@ -module ietf-mpls-holo-deviations { +module holo-ietf-mpls-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-mpls-holo-deviations"; - prefix ietf-mpls-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-mpls-deviations"; + prefix holo-ietf-mpls-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-mpls-ldp-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-mpls-ldp-deviations.yang similarity index 96% rename from holo-yang/modules/deviations/ietf-mpls-ldp-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-mpls-ldp-deviations.yang index 7eaa2232..bff564ae 100644 --- a/holo-yang/modules/deviations/ietf-mpls-ldp-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-mpls-ldp-deviations.yang @@ -1,7 +1,7 @@ -module ietf-mpls-ldp-holo-deviations { +module holo-ietf-mpls-ldp-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-mpls-ldp-holo-deviations"; - prefix ietf-mpls-ldp-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-mpls-ldp-deviations"; + prefix holo-ietf-mpls-ldp-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-ospf-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-ospf-deviations.yang similarity index 99% rename from holo-yang/modules/deviations/ietf-ospf-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-ospf-deviations.yang index 6a9e65ff..78387dc6 100644 --- a/holo-yang/modules/deviations/ietf-ospf-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-ospf-deviations.yang @@ -1,7 +1,7 @@ -module ietf-ospf-holo-deviations { +module holo-ietf-ospf-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-ospf-holo-deviations"; - prefix ietf-ospf-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-ospf-deviations"; + prefix holo-ietf-ospf-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-ospf-sr-mpls-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-ospf-sr-mpls-deviations.yang similarity index 99% rename from holo-yang/modules/deviations/ietf-ospf-sr-mpls-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-ospf-sr-mpls-deviations.yang index 439fe875..f62d4bdc 100644 --- a/holo-yang/modules/deviations/ietf-ospf-sr-mpls-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-ospf-sr-mpls-deviations.yang @@ -1,7 +1,7 @@ -module ietf-ospf-sr-mpls-holo-deviations { +module holo-ietf-ospf-sr-mpls-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-ospf-sr-mpls-holo-deviations"; - prefix ietf-ospf-sr-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-ospf-sr-mpls-deviations"; + prefix holo-ietf-ospf-sr-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-ospfv3-extended-lsa-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-ospfv3-extended-lsa-deviations.yang similarity index 98% rename from holo-yang/modules/deviations/ietf-ospfv3-extended-lsa-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-ospfv3-extended-lsa-deviations.yang index 76bf0e52..99b64dca 100644 --- a/holo-yang/modules/deviations/ietf-ospfv3-extended-lsa-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-ospfv3-extended-lsa-deviations.yang @@ -1,7 +1,7 @@ -module ietf-ospfv3-extended-lsa-holo-deviations { +module holo-ietf-ospfv3-extended-lsa-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-ospfv3-extended-lsa-holo-deviations"; - prefix ietf-ospfv3-extended-lsa-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-ospfv3-extended-lsa-deviations"; + prefix holo-ietf-ospfv3-extended-lsa-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-rip-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-rip-deviations.yang similarity index 98% rename from holo-yang/modules/deviations/ietf-rip-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-rip-deviations.yang index 9e15b4a3..01e579b1 100644 --- a/holo-yang/modules/deviations/ietf-rip-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-rip-deviations.yang @@ -1,7 +1,7 @@ -module ietf-rip-holo-deviations { +module holo-ietf-rip-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-rip-holo-deviations"; - prefix ietf-rip-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-rip-deviations"; + prefix holo-ietf-rip-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-routing-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-routing-deviations.yang similarity index 75% rename from holo-yang/modules/deviations/ietf-routing-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-routing-deviations.yang index d26fe5f3..3554080d 100644 --- a/holo-yang/modules/deviations/ietf-routing-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-routing-deviations.yang @@ -1,7 +1,7 @@ -module ietf-routing-holo-deviations { +module holo-ietf-routing-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-routing-holo-deviations"; - prefix ietf-routing-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-routing-deviations"; + prefix holo-ietf-routing-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-routing-policy-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-routing-policy-deviations.yang similarity index 84% rename from holo-yang/modules/deviations/ietf-routing-policy-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-routing-policy-deviations.yang index c3a14ad6..56964577 100644 --- a/holo-yang/modules/deviations/ietf-routing-policy-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-routing-policy-deviations.yang @@ -1,7 +1,7 @@ -module ietf-routing-policy-holo-deviations { +module holo-ietf-routing-policy-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-routing-policy-holo-deviations"; - prefix ietf-routing-policy-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-routing-policy-deviations"; + prefix holo-ietf-routing-policy-deviations; import ietf-routing-policy { prefix rt-pol; diff --git a/holo-yang/modules/deviations/ietf-segment-routing-mpls-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-segment-routing-mpls-deviations.yang similarity index 97% rename from holo-yang/modules/deviations/ietf-segment-routing-mpls-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-segment-routing-mpls-deviations.yang index 8dd2f05e..65c7cf4b 100644 --- a/holo-yang/modules/deviations/ietf-segment-routing-mpls-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-segment-routing-mpls-deviations.yang @@ -1,7 +1,7 @@ -module ietf-segment-routing-mpls-holo-deviations { +module holo-ietf-segment-routing-mpls-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-segment-routing-mpls-holo-deviations"; - prefix ietf-segment-routing-mpls-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-segment-routing-mpls-deviations"; + prefix holo-ietf-segment-routing-mpls-deviations; import ietf-routing { prefix rt; diff --git a/holo-yang/modules/deviations/ietf-system-holo-deviations.yang b/holo-yang/modules/deviations/holo-ietf-system-deviations.yang similarity index 96% rename from holo-yang/modules/deviations/ietf-system-holo-deviations.yang rename to holo-yang/modules/deviations/holo-ietf-system-deviations.yang index 0bc13fa5..531aad5f 100644 --- a/holo-yang/modules/deviations/ietf-system-holo-deviations.yang +++ b/holo-yang/modules/deviations/holo-ietf-system-deviations.yang @@ -1,7 +1,7 @@ -module ietf-system-holo-deviations { +module holo-ietf-system-deviations { yang-version 1.1; - namespace "http://holo-routing.org/yang/ietf-system-holo-deviations"; - prefix ietf-system-holo-deviations; + namespace "http://holo-routing.org/yang/holo-ietf-system-deviations"; + prefix holo-ietf-system-deviations; import ietf-system { prefix sys; diff --git a/holo-yang/src/lib.rs b/holo-yang/src/lib.rs index b433482e..6e11cabf 100644 --- a/holo-yang/src/lib.rs +++ b/holo-yang/src/lib.rs @@ -131,40 +131,40 @@ pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { EmbeddedModuleKey::new("holo-ospf-dev", None, None, None) => include_str!("../modules/augmentations/holo-ospf-dev.yang"), // IETF Holo deviations - EmbeddedModuleKey::new("ietf-bgp-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-bgp-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-mpls-ldp-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-mpls-ldp-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-if-extensions-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-if-extensions-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-if-vlan-encapsulation-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-if-vlan-encapsulation-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-interfaces-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-interfaces-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-ip-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-ip-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-mpls-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-mpls-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-key-chain-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-key-chain-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-ospf-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-ospf-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-ospf-sr-mpls-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-ospf-sr-mpls-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-ospfv3-extended-lsa-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-ospfv3-extended-lsa-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-rip-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-rip-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-system-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-system-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-routing-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-routing-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-ipv6-unicast-routing-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-ipv6-unicast-routing-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-routing-policy-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-routing-policy-holo-deviations.yang"), - EmbeddedModuleKey::new("ietf-segment-routing-mpls-holo-deviations", None, None, None) => - include_str!("../modules/deviations/ietf-segment-routing-mpls-holo-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-bgp-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-bgp-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-mpls-ldp-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-mpls-ldp-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-if-extensions-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-if-extensions-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-if-vlan-encapsulation-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-if-vlan-encapsulation-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-interfaces-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-interfaces-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-ip-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-ip-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-mpls-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-mpls-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-key-chain-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-key-chain-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-ospf-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-ospf-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-ospf-sr-mpls-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-ospf-sr-mpls-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-ospfv3-extended-lsa-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-ospfv3-extended-lsa-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-rip-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-rip-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-system-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-system-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-routing-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-routing-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-ipv6-unicast-routing-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-ipv6-unicast-routing-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-routing-policy-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-routing-policy-deviations.yang"), + EmbeddedModuleKey::new("holo-ietf-segment-routing-mpls-deviations", None, None, None) => + include_str!("../modules/deviations/holo-ietf-segment-routing-mpls-deviations.yang"), } }); @@ -351,7 +351,7 @@ pub fn load_module(ctx: &mut Context, name: &str) { // Loads a YANG deviations module. pub fn load_deviations(ctx: &mut Context, name: &str) { - let name = format!("{}-holo-deviations", name); + let name = format!("holo-{}-deviations", name); // Ignore errors since the deviation module might not exist. let _ = ctx.load_module(&name, None, &[]); } From 2f790b6473e94a499f83456a7db265f417451e09 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 13 Jul 2024 15:48:20 -0300 Subject: [PATCH 13/14] chore: bump yang3 to 0.5 Signed-off-by: Renato Westphal --- Cargo.toml | 2 +- holo-northbound/build.rs | 12 ++++-------- holo-utils/src/yang.rs | 16 ++++++---------- holo-yang/Cargo.toml | 2 +- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a00bbdc8..59bcbfa9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,7 @@ tonic = { version = "0.11", features = ["tls"] } tonic-build = "0.11" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } -yang3 = { version = "0.1", features = ["bundled"] } +yang3 = { version = "0.5", features = ["bundled"] } [workspace.lints.rust] rust_2018_idioms = { level = "warn", priority = -1 } diff --git a/holo-northbound/build.rs b/holo-northbound/build.rs index dc6db915..2869f292 100644 --- a/holo-northbound/build.rs +++ b/holo-northbound/build.rs @@ -552,15 +552,11 @@ fn generate_module(output: &mut String, snode: &SchemaNode<'_>, level: usize) { } // Iterate over child nodes. - if let Some(actions) = snode.actions() { - for snode in actions { - generate_module(output, &snode, level + 1); - } + for snode in snode.actions() { + generate_module(output, &snode, level + 1); } - if let Some(notifications) = snode.notifications() { - for snode in notifications { - generate_module(output, &snode, level + 1); - } + for snode in snode.notifications() { + generate_module(output, &snode, level + 1); } for snode in snode.children().filter(|snode| snode.is_status_current()) { writeln!(output).unwrap(); diff --git a/holo-utils/src/yang.rs b/holo-utils/src/yang.rs index fc6b30a2..c809a0b5 100644 --- a/holo-utils/src/yang.rs +++ b/holo-utils/src/yang.rs @@ -72,18 +72,14 @@ impl ContextExt for Context { fn cache_data_paths(&self) { for snode in self.traverse() { snode.cache_data_path(); - if let Some(actions) = snode.actions() { - for action in actions { - for snode in action.traverse() { - snode.cache_data_path(); - } + for action in snode.actions() { + for snode in action.traverse() { + snode.cache_data_path(); } } - if let Some(notifications) = snode.notifications() { - for notification in notifications { - for snode in notification.traverse() { - snode.cache_data_path(); - } + for notification in snode.notifications() { + for snode in notification.traverse() { + snode.cache_data_path(); } } } diff --git a/holo-yang/Cargo.toml b/holo-yang/Cargo.toml index fde09c92..c098a06c 100644 --- a/holo-yang/Cargo.toml +++ b/holo-yang/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "holo-yang" -version = "0.5.2" +version = "0.5.3" authors.workspace = true license.workspace = true edition.workspace = true From 79fb0d769a84c6fa1c23513264b627f9e21e7605 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 13 Jul 2024 19:39:40 -0300 Subject: [PATCH 14/14] grpc: add support for LYB binary YANG data format This commit updates the .proto file to allow instance data to be represented as either a string or binary data. This change is necessary because, in Rust, the `String` type cannot contain invalid UTF-8, which might be the case for LYB binary data. The introduction of the "oneof data" field increases complexity, as it introduces two possible fields to hold the data. However, this is necessary to support binary data. An alternative approach would be to use the "bytes" type exclusively for both text and binary data, but this would require clients to convert bytes to text (for XML and JSON), which can incur significant overhead in some languages. Performance tests indicate that using the LYB data format improves the holo-cli "show" commands' performance by approximately 30%. Signed-off-by: Renato Westphal --- holo-daemon/src/northbound/client/grpc.rs | 220 +++++++++++++--------- proto/holo.proto | 9 +- 2 files changed, 143 insertions(+), 86 deletions(-) diff --git a/holo-daemon/src/northbound/client/grpc.rs b/holo-daemon/src/northbound/client/grpc.rs index 8fc118e2..2ad1a097 100644 --- a/holo-daemon/src/northbound/client/grpc.rs +++ b/holo-daemon/src/northbound/client/grpc.rs @@ -115,17 +115,10 @@ impl proto::Northbound for NorthboundService { if with_defaults { printer_flags.insert(DataPrinterFlags::WD_ALL); } - let data = nb_response - .dtree - .print_string(DataFormat::from(encoding), printer_flags) - .map_err(|error| Status::internal(error.to_string()))? - .unwrap_or_default(); + let data = data_tree_init(&nb_response.dtree, encoding, printer_flags)?; let grpc_response = proto::GetResponse { timestamp: get_timestamp(), - data: Some(proto::DataTree { - encoding: encoding as i32, - data, - }), + data: Some(data), }; Ok(Response::new(grpc_response)) } @@ -134,7 +127,6 @@ impl proto::Northbound for NorthboundService { &self, grpc_request: Request, ) -> Result, Status> { - let yang_ctx = YANG_CTX.get().unwrap(); let grpc_request = grpc_request.into_inner(); debug_span!("northbound").in_scope(|| { debug_span!("client", name = "grpc").in_scope(|| { @@ -147,19 +139,10 @@ impl proto::Northbound for NorthboundService { let (responder_tx, responder_rx) = oneshot::channel(); // Convert and relay gRPC request to the northbound. - let config_tree = grpc_request.config.ok_or_else(|| { + let config = grpc_request.config.ok_or_else(|| { Status::invalid_argument("Missing 'config' field") })?; - let encoding = proto::Encoding::try_from(config_tree.encoding) - .map_err(|_| Status::invalid_argument("Invalid data encoding"))?; - let config = DataTree::parse_string( - yang_ctx, - &config_tree.data, - DataFormat::from(encoding), - DataParserFlags::empty(), - DataValidationFlags::NO_STATE, - ) - .map_err(|error| Status::invalid_argument(error.to_string()))?; + let config = data_tree_get(&config)?; let nb_request = api::client::Request::Validate(api::client::ValidateRequest { config, @@ -179,7 +162,6 @@ impl proto::Northbound for NorthboundService { &self, grpc_request: Request, ) -> Result, Status> { - let yang_ctx = YANG_CTX.get().unwrap(); let grpc_request = grpc_request.into_inner(); debug_span!("northbound").in_scope(|| { debug_span!("client", name = "grpc").in_scope(|| { @@ -192,11 +174,9 @@ impl proto::Northbound for NorthboundService { let (responder_tx, responder_rx) = oneshot::channel(); // Convert and relay gRPC request to the northbound. - let config_tree = grpc_request.config.ok_or_else(|| { + let config = grpc_request.config.ok_or_else(|| { Status::invalid_argument("Missing 'config' field") })?; - let encoding = proto::Encoding::try_from(config_tree.encoding) - .map_err(|_| Status::invalid_argument("Invalid data encoding"))?; let operation = proto::commit_request::Operation::try_from(grpc_request.operation) .map_err(|_| { @@ -204,37 +184,15 @@ impl proto::Northbound for NorthboundService { })?; let config = match operation { proto::commit_request::Operation::Merge => { - let config = DataTree::parse_string( - yang_ctx, - &config_tree.data, - DataFormat::from(encoding), - DataParserFlags::empty(), - DataValidationFlags::NO_STATE, - ) - .map_err(|error| Status::invalid_argument(error.to_string()))?; + let config = data_tree_get(&config)?; api::CommitConfiguration::Merge(config) } proto::commit_request::Operation::Replace => { - let config = DataTree::parse_string( - yang_ctx, - &config_tree.data, - DataFormat::from(encoding), - DataParserFlags::empty(), - DataValidationFlags::NO_STATE, - ) - .map_err(|error| Status::invalid_argument(error.to_string()))?; + let config = data_tree_get(&config)?; api::CommitConfiguration::Replace(config) } proto::commit_request::Operation::Change => { - let diff = DataDiff::parse_string( - yang_ctx, - &config_tree.data, - DataFormat::from(encoding), - DataParserFlags::NO_VALIDATION, - DataValidationFlags::NO_STATE - | DataValidationFlags::PRESENT, - ) - .map_err(|error| Status::invalid_argument(error.to_string()))?; + let diff = data_diff_get(&config)?; api::CommitConfiguration::Change(diff) } }; @@ -262,7 +220,6 @@ impl proto::Northbound for NorthboundService { &self, grpc_request: Request, ) -> Result, Status> { - let yang_ctx = YANG_CTX.get().unwrap(); let grpc_request = grpc_request.into_inner(); debug_span!("northbound").in_scope(|| { debug_span!("client", name = "grpc").in_scope(|| { @@ -280,13 +237,7 @@ impl proto::Northbound for NorthboundService { .ok_or_else(|| Status::invalid_argument("Missing 'data' field"))?; let encoding = proto::Encoding::try_from(data.encoding) .map_err(|_| Status::invalid_argument("Invalid data encoding"))?; - let data = DataTree::parse_op_string( - yang_ctx, - &data.data, - DataFormat::from(encoding), - DataOperation::RpcYang, - ) - .map_err(|error| Status::invalid_argument(error.to_string()))?; + let data = rpc_get(&data)?; let nb_request = api::client::Request::Execute(api::client::ExecuteRequest { data, @@ -298,20 +249,9 @@ impl proto::Northbound for NorthboundService { let nb_response = responder_rx.await.unwrap()?; // Convert and relay northbound response to the gRPC client. - let data = nb_response - .data - .print_string( - DataFormat::from(encoding), - DataPrinterFlags::WITH_SIBLINGS, - ) - .map_err(|error| Status::internal(error.to_string()))? - .unwrap_or_default(); - let grpc_response = proto::ExecuteResponse { - data: Some(proto::DataTree { - encoding: encoding as i32, - data, - }), - }; + let printer_flags = DataPrinterFlags::WITH_SIBLINGS; + let data = data_tree_init(&nb_response.data, encoding, printer_flags)?; + let grpc_response = proto::ExecuteResponse { data: Some(data) }; Ok(Response::new(grpc_response)) } @@ -391,19 +331,11 @@ impl proto::Northbound for NorthboundService { // Convert and relay northbound response to the gRPC client. let encoding = proto::Encoding::try_from(grpc_request.encoding) .map_err(|_| Status::invalid_argument("Invalid data encoding"))?; - let config = nb_response - .dtree - .print_string( - DataFormat::from(encoding), - DataPrinterFlags::WITH_SIBLINGS, - ) - .map_err(|error| Status::internal(error.to_string()))? - .unwrap_or_default(); + let printer_flags = DataPrinterFlags::WITH_SIBLINGS; + let config = + data_tree_init(&nb_response.dtree, encoding, printer_flags)?; let grpc_response = proto::GetTransactionResponse { - config: Some(proto::DataTree { - encoding: encoding as i32, - data: config, - }), + config: Some(config), }; Ok(Response::new(grpc_response)) } @@ -474,7 +406,7 @@ impl TryFrom for api::DataType { } } -// ===== global functions ===== +// ===== helper functions ===== fn get_timestamp() -> i64 { SystemTime::now() @@ -483,6 +415,124 @@ fn get_timestamp() -> i64 { .as_secs() as i64 } +fn data_tree_init( + dtree: &DataTree, + encoding: proto::Encoding, + printer_flags: DataPrinterFlags, +) -> Result { + let data_format = DataFormat::from(encoding); + let data = match data_format { + DataFormat::JSON | DataFormat::XML => { + let string = dtree + .print_string(data_format, printer_flags) + .map_err(|error| Status::internal(error.to_string()))? + .unwrap_or_default(); + proto::data_tree::Data::DataString(string) + } + DataFormat::LYB => { + let bytes = dtree + .print_bytes(data_format, printer_flags) + .map_err(|error| Status::internal(error.to_string()))? + .unwrap_or_default(); + proto::data_tree::Data::DataBytes(bytes) + } + }; + + Ok(proto::DataTree { + encoding: encoding as i32, + data: Some(data), + }) +} + +fn data_tree_get(data_tree: &proto::DataTree) -> Result { + let yang_ctx = YANG_CTX.get().unwrap(); + let encoding = proto::Encoding::try_from(data_tree.encoding) + .map_err(|_| Status::invalid_argument("Invalid data encoding"))?; + let data_format = DataFormat::from(encoding); + let parser_flags = DataParserFlags::empty(); + let validation_flags = DataValidationFlags::NO_STATE; + let data = data_tree + .data + .as_ref() + .ok_or_else(|| Status::invalid_argument("Missing 'data' field"))?; + match data { + proto::data_tree::Data::DataString(data) => DataTree::parse_string( + yang_ctx, + data, + data_format, + parser_flags, + validation_flags, + ), + proto::data_tree::Data::DataBytes(data) => DataTree::parse_string( + yang_ctx, + data, + data_format, + parser_flags, + validation_flags, + ), + } + .map_err(|error| Status::invalid_argument(error.to_string())) +} + +fn data_diff_get(data_tree: &proto::DataTree) -> Result { + let yang_ctx = YANG_CTX.get().unwrap(); + let encoding = proto::Encoding::try_from(data_tree.encoding) + .map_err(|_| Status::invalid_argument("Invalid data encoding"))?; + let data_format = DataFormat::from(encoding); + let parser_flags = DataParserFlags::NO_VALIDATION; + let validation_flags = + DataValidationFlags::NO_STATE | DataValidationFlags::PRESENT; + let data = data_tree + .data + .as_ref() + .ok_or_else(|| Status::invalid_argument("Missing 'data' field"))?; + match data { + proto::data_tree::Data::DataString(data) => DataDiff::parse_string( + yang_ctx, + data, + data_format, + parser_flags, + validation_flags, + ), + proto::data_tree::Data::DataBytes(data) => DataDiff::parse_string( + yang_ctx, + data, + data_format, + parser_flags, + validation_flags, + ), + } + .map_err(|error| Status::invalid_argument(error.to_string())) +} + +fn rpc_get(data_tree: &proto::DataTree) -> Result { + let yang_ctx = YANG_CTX.get().unwrap(); + let encoding = proto::Encoding::try_from(data_tree.encoding) + .map_err(|_| Status::invalid_argument("Invalid data encoding"))?; + let data_format = DataFormat::from(encoding); + let data = data_tree + .data + .as_ref() + .ok_or_else(|| Status::invalid_argument("Missing 'data' field"))?; + match data { + proto::data_tree::Data::DataString(data) => DataTree::parse_op_string( + yang_ctx, + data, + data_format, + DataOperation::RpcYang, + ), + proto::data_tree::Data::DataBytes(data) => DataTree::parse_op_string( + yang_ctx, + data, + data_format, + DataOperation::RpcYang, + ), + } + .map_err(|error| Status::invalid_argument(error.to_string())) +} + +// ===== global functions ===== + pub(crate) fn start( config: &config::Grpc, request_tx: Sender, diff --git a/proto/holo.proto b/proto/holo.proto index 61675e21..985c0f7d 100644 --- a/proto/holo.proto +++ b/proto/holo.proto @@ -242,6 +242,13 @@ enum Encoding { // YANG instance data. message DataTree { + // The encoding format of the data. Encoding encoding = 1; - string data = 2; + + oneof data { + // Data in string format, used for JSON or XML encodings. + string data_string = 2; + // Data in binary format, used for LYB encoding. + bytes data_bytes = 3; + } }