From 63f48efec9a299ec755113229396278a098fd387 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 15 Feb 2025 22:48:12 -0300 Subject: [PATCH] isis: set ATT bit in L1 LSPs when connected to L2 backbone This is necessary for L1 routers within the same area to compute default routes to reach inter-area destinations. Signed-off-by: Renato Westphal --- holo-isis/src/instance.rs | 15 ++++++++++++++- holo-isis/src/lsdb.rs | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/holo-isis/src/instance.rs b/holo-isis/src/instance.rs index 75ee1ede..4802ca2b 100644 --- a/holo-isis/src/instance.rs +++ b/holo-isis/src/instance.rs @@ -23,7 +23,7 @@ use holo_utils::{Receiver, Sender, UnboundedReceiver, UnboundedSender}; use ipnetwork::IpNetwork; use tokio::sync::mpsc; -use crate::adjacency::Adjacency; +use crate::adjacency::{Adjacency, AdjacencyState}; use crate::collections::{Arena, Interfaces, Lsdb, LspEntryId}; use crate::debug::{ Debug, InstanceInactiveReason, InterfaceInactiveReason, LspPurgeReason, @@ -496,6 +496,19 @@ impl MessageReceiver for ProtocolInputChannelsRx { // ===== impl InstanceUpView ===== impl InstanceUpView<'_> { + // Checks if the instance is attached to the Level 2 backbone. + pub(crate) fn is_l2_attached_to_backbone( + &self, + interfaces: &Interfaces, + adjacencies: &Arena, + ) -> bool { + interfaces + .iter() + .flat_map(|iface| iface.adjacencies(adjacencies)) + .filter(|adj| adj.state == AdjacencyState::Up) + .any(|adj| adj.level_usage.intersects(LevelNumber::L2)) + } + pub(crate) fn schedule_lsp_origination( &mut self, level_type: impl Into, diff --git a/holo-isis/src/lsdb.rs b/holo-isis/src/lsdb.rs index 7ccb780e..1e9cfe4c 100644 --- a/holo-isis/src/lsdb.rs +++ b/holo-isis/src/lsdb.rs @@ -29,7 +29,7 @@ use crate::packet::tlv::{ ExtIpv4Reach, ExtIsReach, Ipv4Reach, Ipv6Reach, IsReach, MAX_NARROW_METRIC, Nlpid, }; -use crate::packet::{LanId, LevelNumber, LspId}; +use crate::packet::{LanId, LevelNumber, LevelType, LspId}; use crate::spf::SpfType; use crate::tasks::messages::input::LspPurgeMsg; use crate::{spf, tasks}; @@ -149,6 +149,8 @@ fn lsp_build( fn lsp_build_flags( instance: &mut InstanceUpView<'_>, + arenas: &InstanceArenas, + level: LevelNumber, lsp_id: LspId, ) -> LspFlags { let mut lsp_flags = LspFlags::default(); @@ -158,6 +160,15 @@ fn lsp_build_flags( if instance.config.level_type.intersects(LevelNumber::L2) { lsp_flags.insert(LspFlags::IS_TYPE2); } + if instance.config.level_type == LevelType::All + && level == LevelNumber::L1 + && lsp_id.pseudonode == 0 + && lsp_id.fragment == 0 + && instance + .is_l2_attached_to_backbone(&arenas.interfaces, &arenas.adjacencies) + { + lsp_flags.insert(LspFlags::ATT); + } if instance.config.overload_status && lsp_id.pseudonode == 0 && lsp_id.fragment == 0 @@ -410,7 +421,7 @@ fn lsp_build_fragments( .get_by_lspid(&arenas.lsp_entries, &lsp_id) .map(|(_, lse)| lse.data.seqno + 1) .unwrap_or(LSP_INIT_SEQNO); - let lsp_flags = lsp_build_flags(instance, lsp_id); + let lsp_flags = lsp_build_flags(instance, arenas, level, lsp_id); let fragment = Lsp::new( level, instance.config.lsp_lifetime,