Skip to content

Commit

Permalink
isis: handle ATT bit in SPF for default routes to nearest L1/L2 routers
Browse files Browse the repository at this point in the history
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
  • Loading branch information
rwestphal committed Feb 16, 2025
1 parent 63f48ef commit a71826e
Showing 1 changed file with 47 additions and 6 deletions.
53 changes: 47 additions & 6 deletions holo-isis/src/spf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::time::{Duration, Instant};

use chrono::Utc;
use derive_new::new;
use holo_utils::ip::AddressFamily;
use holo_utils::ip::{AddressFamily, IpNetworkKind};
use holo_utils::task::TimeoutTask;
use ipnetwork::IpNetwork;
use tracing::debug_span;
Expand Down Expand Up @@ -402,7 +402,8 @@ fn compute_spf(
}

// Compute routing table.
let mut rib = compute_routes(level, instance, lsp_entries);
let mut rib =
compute_routes(level, instance, interfaces, adjacencies, lsp_entries);

// Update local routing table
match instance.config.level_type {
Expand Down Expand Up @@ -612,6 +613,8 @@ fn compute_spt(
fn compute_routes(
level: LevelNumber,
instance: &InstanceUpView<'_>,
interfaces: &Interfaces,
adjacencies: &Arena<Adjacency>,
lsp_entries: &Arena<LspEntry>,
) -> BTreeMap<IpNetwork, Route> {
let lsdb = instance.state.lsdb.get(level);
Expand All @@ -621,6 +624,8 @@ fn compute_routes(
let mut rib = BTreeMap::new();

// Populate RIB.
let is_l2_attached_to_backbone =
instance.is_l2_attached_to_backbone(interfaces, adjacencies);
let ipv4_enabled = instance.config.is_af_enabled(AddressFamily::Ipv4);
let ipv6_enabled = instance.config.is_af_enabled(AddressFamily::Ipv6);
for vertex in instance
Expand All @@ -631,13 +636,17 @@ fn compute_routes(
.filter(|vertex| vertex.hops > 0)
{
// Skip if the zeroth LSP is missing.
let Some(_zeroth_lsp) = zeroth_lsp(vertex.id.lan_id, lsdb, lsp_entries)
let Some(zeroth_lsp) = zeroth_lsp(vertex.id.lan_id, lsdb, lsp_entries)
else {
continue;
};

for network in vertex_networks(
&vertex.id,
instance.config.level_type,
level,
vertex,
zeroth_lsp.flags.contains(LspFlags::ATT),
is_l2_attached_to_backbone,
metric_type,
ipv4_enabled,
ipv6_enabled,
Expand Down Expand Up @@ -789,23 +798,54 @@ fn vertex_edges<'a>(

// Iterate over all IP reachability entries attached to a vertex.
fn vertex_networks<'a>(
vertex_id: &VertexId,
level_type: LevelType,
level: LevelNumber,
vertex: &Vertex,
att_bit: bool,
is_l2_attached_to_backbone: bool,
metric_type: MetricType,
ipv4_enabled: bool,
ipv6_enabled: bool,
lsdb: &'a Lsdb,
lsp_entries: &'a Arena<LspEntry>,
) -> impl Iterator<Item = VertexNetwork> + 'a {
// Iterate over all LSP fragments.
lsdb.iter_for_lan_id(lsp_entries, vertex_id.lan_id)
lsdb.iter_for_lan_id(lsp_entries, vertex.id.lan_id)
.map(|lse| &lse.data)
.filter(|lsp| lsp.seqno != 0)
.filter(|lsp| lsp.rem_lifetime != 0)
.flat_map(move |lsp| {
let mut inter_area_defaults_iter = None;
let mut ipv4_standard_iter = None;
let mut ipv4_wide_iter = None;
let mut ipv6_iter = None;

// If the L1 LSP has the ATT bit set, add a default route if the
// router is L1, or if the router is L1/L2 but not attached to the
// L2 backbone.
if att_bit
&& level == LevelNumber::L1
&& (level_type == LevelType::L1 || !is_l2_attached_to_backbone)
{
let mut inter_area_defaults = vec![];
if ipv4_enabled {
inter_area_defaults.push(VertexNetwork {
prefix: IpNetwork::default(AddressFamily::Ipv4),
metric: 0,
external: false,
});
}
if ipv6_enabled {
inter_area_defaults.push(VertexNetwork {
prefix: IpNetwork::default(AddressFamily::Ipv6),
metric: 0,
external: false,
});
}
inter_area_defaults_iter =
Some(inter_area_defaults.into_iter());
}

// Iterate over IPv4 reachability entries.
if ipv4_enabled {
if metric_type.is_standard_enabled() {
Expand Down Expand Up @@ -869,6 +909,7 @@ fn vertex_networks<'a>(
}

chain_option_iterators!(
inter_area_defaults_iter,
ipv4_standard_iter,
ipv4_wide_iter,
ipv6_iter,
Expand Down

0 comments on commit a71826e

Please sign in to comment.