From 3764c57ccb92a4ebe9af567bc0d9a429ceb7cc95 Mon Sep 17 00:00:00 2001 From: nrybowski Date: Tue, 20 Aug 2024 10:37:08 +0200 Subject: [PATCH] bier,ospf: Handle configuration events - Handle BIER enable / disable by re-installing routes in the BIRT / purging the BIRT, and re-originating self-LSA to advertise the update - Handle BIER sub-domain configuration events by re-originating self-LSA - Handle BIER encapsulation configuration events by re-originating self-LSA Signed-off-by: Nicolas Rybowski --- holo-ospf/src/events.rs | 23 +++++++++++++++++++- holo-ospf/src/instance.rs | 4 ++++ holo-ospf/src/lsdb.rs | 6 ++++- holo-ospf/src/northbound/configuration.rs | 22 +++++++++++++++++++ holo-ospf/src/ospfv3/lsdb.rs | 19 +++++++++++++++- holo-ospf/src/southbound/tx.rs | 17 +++++++++++++-- holo-routing/src/ibus.rs | 6 +++++ holo-routing/src/northbound/configuration.rs | 20 +++++++++++++++-- holo-routing/src/rib.rs | 9 ++++++-- holo-utils/src/ibus.rs | 17 +++++++++------ holo-utils/src/southbound.rs | 10 ++++++++- 11 files changed, 136 insertions(+), 17 deletions(-) diff --git a/holo-ospf/src/events.rs b/holo-ospf/src/events.rs index 4562b086..09af5c8b 100644 --- a/holo-ospf/src/events.rs +++ b/holo-ospf/src/events.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use chrono::Utc; use holo_utils::bfd; -use holo_utils::ibus::SrCfgEvent; +use holo_utils::ibus::{BierCfgEvent, SrCfgEvent}; use crate::area::{Area, AreaType}; use crate::collections::{ @@ -1429,6 +1429,27 @@ where Ok(()) } +// ===== BIER configuration change event ===== + +pub(crate) fn process_bier_cfg_change( + instance: &mut Instance, + change: BierCfgEvent, +) -> Result<(), Error> +where + V: Version, +{ + if let Some((instance, arenas)) = instance.as_up() + && instance.config.bier.enabled + { + V::lsa_orig_event( + &instance, + arenas, + LsaOriginateEvent::BierCfgChange { change }, + )?; + } + Ok(()) +} + // ===== BFD state update event ===== pub(crate) fn process_bfd_state_update( diff --git a/holo-ospf/src/instance.rs b/holo-ospf/src/instance.rs index 70bddc6b..3a516637 100644 --- a/holo-ospf/src/instance.rs +++ b/holo-ospf/src/instance.rs @@ -780,6 +780,7 @@ where IbusMsg::SrCfgUpd(sr_config) => { instance.shared.sr_config = sr_config; } + // BIER configuration update. IbusMsg::BierCfgUpd(bier_config) => { instance.shared.bier_config = bier_config.clone(); } @@ -787,6 +788,9 @@ where IbusMsg::SrCfgEvent(event) => { events::process_sr_cfg_change(instance, event)? } + IbusMsg::BierCfgEvent(event) => { + events::process_bier_cfg_change(instance, event)? + } // Ignore other events. _ => {} } diff --git a/holo-ospf/src/lsdb.rs b/holo-ospf/src/lsdb.rs index c78ad41f..24a106dc 100644 --- a/holo-ospf/src/lsdb.rs +++ b/holo-ospf/src/lsdb.rs @@ -13,7 +13,7 @@ use std::time::Instant; use bitflags::bitflags; use chrono::Utc; use derive_new::new; -use holo_utils::ibus::SrCfgEvent; +use holo_utils::ibus::{BierCfgEvent, SrCfgEvent}; use holo_utils::task::TimeoutTask; use holo_utils::UnboundedSender; use serde::{Deserialize, Serialize}; @@ -124,6 +124,10 @@ pub enum LsaOriginateEvent { area_id: AreaId, iface_id: InterfaceId, }, + BierEnableChange, + BierCfgChange { + change: BierCfgEvent, + }, } #[derive(Debug)] diff --git a/holo-ospf/src/northbound/configuration.rs b/holo-ospf/src/northbound/configuration.rs index bb3253b9..ac01a769 100644 --- a/holo-ospf/src/northbound/configuration.rs +++ b/holo-ospf/src/northbound/configuration.rs @@ -72,6 +72,7 @@ pub enum Event { RerunSpf, UpdateSummaries, ReinstallRoutes, + BierEnableChange(bool), } pub static VALIDATION_CALLBACKS_OSPFV2: Lazy = @@ -791,6 +792,8 @@ where .modify_apply(|instance, args| { let mt_id = args.dnode.get_u8(); instance.config.bier.mt_id = mt_id; + + // TODO: should reoriginate LSA }) .delete_apply(|instance, _args| { let mt_id = 0; @@ -800,6 +803,9 @@ where .modify_apply(|instance, args| { let enable = args.dnode.get_bool(); instance.config.bier.enabled = enable; + + let event_queue = args.event_queue; + event_queue.insert(Event::BierEnableChange(enable)); }) .path(ospf::bier_ospf_cfg::bier::advertise::PATH) .modify_apply(|instance, args| { @@ -1504,6 +1510,22 @@ where } } } + Event::BierEnableChange(bier_enabled) => { + if let Some((instance, _arenas)) = self.as_up() { + // (Re)originate LSAs that might have been affected. + instance + .tx + .protocol_input + .lsa_orig_event(LsaOriginateEvent::BierEnableChange); + + // Purge BIRT if bier disabled or re-install routes if enabled + if bier_enabled { + self.process_event(Event::ReinstallRoutes).await; + } else { + let _ = instance.tx.ibus.send(IbusMsg::BierPurge); + } + } + } Event::RerunSpf => { if let Some((instance, _)) = self.as_up() { instance diff --git a/holo-ospf/src/ospfv3/lsdb.rs b/holo-ospf/src/ospfv3/lsdb.rs index 4c644412..f715e295 100644 --- a/holo-ospf/src/ospfv3/lsdb.rs +++ b/holo-ospf/src/ospfv3/lsdb.rs @@ -8,7 +8,7 @@ use std::collections::{hash_map, BTreeMap, HashMap}; use std::net::{IpAddr, Ipv4Addr}; use holo_utils::bier::{BierEncapsulationType, BierInBiftId, BiftId}; -use holo_utils::ibus::SrCfgEvent; +use holo_utils::ibus::{BierCfgEvent, SrCfgEvent}; use holo_utils::ip::{AddressFamily, IpNetworkKind}; use holo_utils::mpls::Label; use holo_utils::sr::{IgpAlgoType, Sid, SidLastHopBehavior}; @@ -281,6 +281,23 @@ impl LsdbVersion for Ospfv3 { } } } + LsaOriginateEvent::BierEnableChange => { + // Reoriginate Intra-area-prefix-LSA(s) in all areas. + for area in arenas.areas.iter() { + lsa_orig_intra_area_prefix(area, instance, arenas); + } + } + LsaOriginateEvent::BierCfgChange { change } => match change { + BierCfgEvent::EncapUpdate(af) + | BierCfgEvent::SubDomainUpdate(af) => { + if af == instance.state.af { + for area in arenas.areas.iter() { + // Reoriginate Intra-area-prefix-LSA(s) in all areas. + lsa_orig_intra_area_prefix(area, instance, arenas); + } + } + } + }, }; Ok(()) diff --git a/holo-ospf/src/southbound/tx.rs b/holo-ospf/src/southbound/tx.rs index 5dc4b5bd..4e455557 100644 --- a/holo-ospf/src/southbound/tx.rs +++ b/holo-ospf/src/southbound/tx.rs @@ -10,8 +10,8 @@ use std::net::IpAddr; use holo_utils::ibus::{IbusMsg, IbusSender}; use holo_utils::mpls::Label; use holo_utils::southbound::{ - BierNbrInstallMsg, LabelInstallMsg, LabelUninstallMsg, Nexthop, - RouteKeyMsg, RouteMsg, RouteOpaqueAttrs, + BierNbrInstallMsg, BierNbrUninstallMsg, LabelInstallMsg, LabelUninstallMsg, + Nexthop, RouteKeyMsg, RouteMsg, RouteOpaqueAttrs, }; use crate::collections::Arena; @@ -140,6 +140,19 @@ pub(crate) fn route_uninstall( let msg = IbusMsg::RouteMplsDel(msg); let _ = ibus_tx.send(msg); } + + // Uninstall BIER neighbor entry + if let Some(bier_info) = &route.bier_info { + for bsl in &bier_info.bfr_bss { + let msg = BierNbrUninstallMsg { + sd_id: bier_info.sd_id, + bfr_id: bier_info.bfr_id, + bsl: *bsl, + }; + let msg = IbusMsg::RouteBierDel(msg); + let _ = ibus_tx.send(msg); + } + } } pub(crate) fn adj_sid_install( diff --git a/holo-routing/src/ibus.rs b/holo-routing/src/ibus.rs index b589f2aa..c741a3e1 100644 --- a/holo-routing/src/ibus.rs +++ b/holo-routing/src/ibus.rs @@ -98,6 +98,12 @@ pub(crate) fn process_msg(master: &mut Master, msg: IbusMsg) { IbusMsg::RouteBierAdd(msg) => { master.birt.bier_nbr_add(msg); } + IbusMsg::RouteBierDel(msg) => { + master.birt.bier_nbr_del(msg); + } + IbusMsg::BierPurge => { + master.birt.entries.clear(); + } // Ignore other events. _ => {} } diff --git a/holo-routing/src/northbound/configuration.rs b/holo-routing/src/northbound/configuration.rs index fb87784d..60639913 100644 --- a/holo-routing/src/northbound/configuration.rs +++ b/holo-routing/src/northbound/configuration.rs @@ -74,6 +74,7 @@ pub enum Event { SrCfgPrefixSidUpdate(AddressFamily), BierCfgUpdate, BierCfgEncapUpdate(SubDomainId, AddressFamily, Bsl, BierEncapsulationType), + BierCfgSubDomainUpdate(AddressFamily), } // ===== configuration structs ===== @@ -665,6 +666,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .delete_apply(|master, args| { let sd_id = args.dnode.get_u8_relative("./sub-domain-id").unwrap(); @@ -673,6 +675,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .lookup(|_master, _list_entry, dnode| { let sd_id = dnode.get_u8_relative("./sub-domain-id").unwrap(); @@ -689,6 +692,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .path(bier::sub_domain::underlay_protocol_type::PATH) .modify_apply(|context, args| { @@ -701,6 +705,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .path(bier::sub_domain::mt_id::PATH) .modify_apply(|context, args| { @@ -712,6 +717,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .path(bier::sub_domain::bfr_id::PATH) .modify_apply(|context, args| { @@ -723,6 +729,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .path(bier::sub_domain::bsl::PATH) .modify_apply(|context, args| { @@ -735,6 +742,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .path(bier::sub_domain::igp_algorithm::PATH) .modify_apply(|context, args| { @@ -746,6 +754,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .path(bier::sub_domain::bier_algorithm::PATH) .modify_apply(|context, args| { @@ -757,6 +766,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .path(bier::sub_domain::load_balance_num::PATH) .modify_apply(|context, args| { @@ -768,6 +778,7 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::BierCfgUpdate); + event_queue.insert(Event::BierCfgSubDomainUpdate(af)); }) .path(bier::sub_domain::encapsulation::PATH) .create_apply(|context, args| { @@ -1062,9 +1073,14 @@ impl Provider for Master { .ibus_tx .send(IbusMsg::BierCfgUpd(self.shared.bier_config.clone())); } - Event::BierCfgEncapUpdate(sd_id, af, bsl, encap_type) => { + Event::BierCfgEncapUpdate(_sd_id, af, _bsl, _encap_type) => { + let _ = self + .ibus_tx + .send(IbusMsg::BierCfgEvent(BierCfgEvent::EncapUpdate(af))); + } + Event::BierCfgSubDomainUpdate(af) => { let _ = self.ibus_tx.send(IbusMsg::BierCfgEvent( - BierCfgEvent::EncapUpdate(sd_id, af, bsl, encap_type), + BierCfgEvent::SubDomainUpdate(af), )); } } diff --git a/holo-routing/src/rib.rs b/holo-routing/src/rib.rs index 14d7c1aa..d2dfc338 100644 --- a/holo-routing/src/rib.rs +++ b/holo-routing/src/rib.rs @@ -16,8 +16,9 @@ use holo_utils::ip::{AddressFamily, IpNetworkExt, Ipv4AddrExt, Ipv6AddrExt}; use holo_utils::mpls::Label; use holo_utils::protocol::Protocol; use holo_utils::southbound::{ - AddressFlags, AddressMsg, BierNbrInstallMsg, LabelInstallMsg, - LabelUninstallMsg, Nexthop, RouteKeyMsg, RouteMsg, RouteOpaqueAttrs, + AddressFlags, AddressMsg, BierNbrInstallMsg, BierNbrUninstallMsg, + LabelInstallMsg, LabelUninstallMsg, Nexthop, RouteKeyMsg, RouteMsg, + RouteOpaqueAttrs, }; use holo_utils::{UnboundedReceiver, UnboundedSender}; use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network}; @@ -83,6 +84,10 @@ impl Birt { } }); } + + pub(crate) fn bier_nbr_del(&mut self, msg: BierNbrUninstallMsg) { + let _ = self.entries.remove(&(msg.sd_id, msg.bfr_id, msg.bsl)); + } } // ===== impl Rib ===== diff --git a/holo-utils/src/ibus.rs b/holo-utils/src/ibus.rs index 4c146157..4a835b3f 100644 --- a/holo-utils/src/ibus.rs +++ b/holo-utils/src/ibus.rs @@ -11,14 +11,14 @@ use serde::{Deserialize, Serialize}; use tokio::sync::broadcast::{Receiver, Sender}; use crate::bfd; -use crate::bier::{BierCfg, BierEncapsulationType, Bsl, SubDomainId}; +use crate::bier::BierCfg; use crate::ip::AddressFamily; use crate::keychain::Keychain; use crate::policy::{MatchSets, Policy}; use crate::protocol::Protocol; use crate::southbound::{ - AddressMsg, BierNbrInstallMsg, InterfaceUpdateMsg, LabelInstallMsg, - LabelUninstallMsg, RouteKeyMsg, RouteMsg, + AddressMsg, BierNbrInstallMsg, BierNbrUninstallMsg, InterfaceUpdateMsg, + LabelInstallMsg, LabelUninstallMsg, RouteKeyMsg, RouteMsg, }; use crate::sr::SrCfg; @@ -112,10 +112,12 @@ pub enum IbusMsg { BierCfgUpd(Arc), // BIER configuration event. BierCfgEvent(BierCfgEvent), - // Request to install an entry in the BIRT + // Request to install an entry in the BIRT. RouteBierAdd(BierNbrInstallMsg), - // Request to uninstall an entry in the BIRT - RouteBierDel(), + // Request to uninstall an entry in the BIRT. + RouteBierDel(BierNbrUninstallMsg), + // Purge the BIRT. + BierPurge, } // Type of Segment Routing configuration change. @@ -128,5 +130,6 @@ pub enum SrCfgEvent { // Type of BIER configuration events. #[derive(Clone, Debug, Deserialize, Serialize)] pub enum BierCfgEvent { - EncapUpdate(SubDomainId, AddressFamily, Bsl, BierEncapsulationType), + SubDomainUpdate(AddressFamily), + EncapUpdate(AddressFamily), } diff --git a/holo-utils/src/southbound.rs b/holo-utils/src/southbound.rs index 2e56ca98..1619940b 100644 --- a/holo-utils/src/southbound.rs +++ b/holo-utils/src/southbound.rs @@ -13,7 +13,7 @@ use holo_yang::{ToYang, TryFromYang}; use ipnetwork::IpNetwork; use serde::{Deserialize, Serialize}; -use crate::bier::BierInfo; +use crate::bier::{BfrId, BierInfo, Bsl, SubDomainId}; use crate::mpls::Label; use crate::protocol::Protocol; @@ -110,6 +110,14 @@ pub struct BierNbrInstallMsg { pub prefix: IpNetwork, } +#[derive(Clone, Debug)] +#[derive(Deserialize, Serialize)] +pub struct BierNbrUninstallMsg { + pub sd_id: SubDomainId, + pub bfr_id: BfrId, + pub bsl: Bsl, +} + #[derive(Clone, Debug)] #[derive(Deserialize, Serialize)] pub struct LabelInstallMsg {