Skip to content

Commit

Permalink
Merge pull request #16 from nrybowski/bier_ospfv3
Browse files Browse the repository at this point in the history
BIER extension for OSPFv3
  • Loading branch information
rwestphal authored Sep 10, 2024
2 parents c370052 + 81a0ab1 commit 1d3461c
Show file tree
Hide file tree
Showing 79 changed files with 1,269 additions and 336 deletions.
57 changes: 57 additions & 0 deletions holo-ospf/src/bier.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// Copyright (c) The Holo Core Contributors
//
// SPDX-License-Identifier: MIT
//

use holo_utils::bier::{BierInfo, Bsl, UnderlayProtocolType};
use holo_utils::ip::IpNetworkKind;

use crate::instance::InstanceUpView;
use crate::packet::tlv::BierSubSubTlv;
use crate::route::RouteNet;
use crate::spf::SpfIntraAreaNetwork;
use crate::version::Version;

pub(crate) fn bier_route_add<V>(
instance: &InstanceUpView<'_, V>,
new_route: &mut RouteNet<V>,
stub: &SpfIntraAreaNetwork<'_, V>,
) where
V: Version,
{
let bier_cfg = &instance.shared.bier_config;

// 1. Does the BFR match a locally configured BIER sub-domain?
stub.bier.iter().for_each(|tlv| {
if instance.config.bier.mt_id == tlv.mt_id
&& let Some(sd_cfg) = bier_cfg
.sd_cfg
.get(&(tlv.sub_domain_id, stub.prefix.address_family()))
&& sd_cfg.underlay_protocol == UnderlayProtocolType::Ospf
{
// 2. Register entry in BIRT for each supported bitstring length by the BFR prefix
// TODO: Use BAR and IPA

// TODO: Sanity check on bitstring lengths upon LSA reception

let bfr_bss: Vec<Bsl> = tlv
.subtlvs
.iter()
.filter_map(|stlv| match stlv {
BierSubSubTlv::BierEncapSubSubTlv(encap) => {
Bsl::try_from(encap.bs_len).ok()
}
})
.collect();

if !bfr_bss.is_empty() {
new_route.bier_info = Some(BierInfo {
bfr_bss,
sd_id: tlv.sub_domain_id,
bfr_id: tlv.bfr_id,
})
}
}
});
}
23 changes: 22 additions & 1 deletion holo-ospf/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -1429,6 +1429,27 @@ where
Ok(())
}

// ===== BIER configuration change event =====

pub(crate) fn process_bier_cfg_change<V>(
instance: &mut Instance<V>,
change: BierCfgEvent,
) -> Result<(), Error<V>>
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<V>(
Expand Down
7 changes: 7 additions & 0 deletions holo-ospf/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,10 +780,17 @@ 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();
}
// SR configuration event.
IbusMsg::SrCfgEvent(event) => {
events::process_sr_cfg_change(instance, event)?
}
IbusMsg::BierCfgEvent(event) => {
events::process_bier_cfg_change(instance, event)?
}
// Ignore other events.
_ => {}
}
Expand Down
1 change: 1 addition & 0 deletions holo-ospf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#![feature(btree_extract_if, hash_extract_if, ip, let_chains)]

pub mod area;
pub mod bier;
pub mod collections;
pub mod debug;
pub mod error;
Expand Down
6 changes: 5 additions & 1 deletion holo-ospf/src/lsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -124,6 +124,10 @@ pub enum LsaOriginateEvent {
area_id: AreaId,
iface_id: InterfaceId,
},
BierEnableChange,
BierCfgChange {
change: BierCfgEvent,
},
}

#[derive(Debug)]
Expand Down
70 changes: 70 additions & 0 deletions holo-ospf/src/northbound/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub enum Event {
RerunSpf,
UpdateSummaries,
ReinstallRoutes,
BierEnableChange(bool),
}

pub static VALIDATION_CALLBACKS_OSPFV2: Lazy<ValidationCallbacks> =
Expand Down Expand Up @@ -102,6 +103,15 @@ pub struct InstanceCfg {
pub extended_lsa: bool,
pub sr_enabled: bool,
pub instance_id: u8,
pub bier: BierOspfCfg,
}

#[derive(Debug)]
pub struct BierOspfCfg {
pub mt_id: u8,
pub enabled: bool,
pub advertise: bool,
pub receive: bool,
}

#[derive(Debug)]
Expand Down Expand Up @@ -778,6 +788,35 @@ where
let mtu_ignore = args.dnode.get_bool();
iface.config.mtu_ignore = mtu_ignore;
})
.path(ospf::bier::mt_id::PATH)
.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;
instance.config.bier.mt_id = mt_id;
})
.path(ospf::bier::bier::enable::PATH)
.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::bier::advertise::PATH)
.modify_apply(|instance, args| {
let advertise = args.dnode.get_bool();
instance.config.bier.advertise = advertise;
})
.path(ospf::bier::bier::receive::PATH)
.modify_apply(|instance, args| {
let receive = args.dnode.get_bool();
instance.config.bier.receive = receive;
})
.build()
}

Expand Down Expand Up @@ -1471,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
Expand Down Expand Up @@ -1559,6 +1614,21 @@ impl Default for InstanceCfg {
extended_lsa,
sr_enabled,
instance_id,
bier: Default::default(),
}
}
}

impl Default for BierOspfCfg {
fn default() -> Self {
let enabled = ospf::bier::bier::enable::DFLT;
let advertise = ospf::bier::bier::advertise::DFLT;
let receive = ospf::bier::bier::receive::DFLT;
Self {
mt_id: 0,
enabled,
advertise,
receive,
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions holo-ospf/src/ospfv2/spf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,8 @@ impl SpfVersion<Self> for Ospfv2 {
prefix_options: Default::default(),
metric: 0,
prefix_sids,
// FIXME: BIER not supported yet for OSPFv2
bier: Default::default(),
});
}
VertexLsa::Router(lsa) => {
Expand Down Expand Up @@ -523,6 +525,8 @@ impl SpfVersion<Self> for Ospfv2 {
prefix_options: Default::default(),
metric,
prefix_sids,
// FIXME: BIER not supported yet for OSPFv2
bier: Default::default(),
}
}),
)
Expand Down
80 changes: 77 additions & 3 deletions holo-ospf/src/ospfv3/lsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
use std::collections::{hash_map, BTreeMap, HashMap};
use std::net::{IpAddr, Ipv4Addr};

use holo_utils::ibus::SrCfgEvent;
use holo_utils::bier::{BierEncapsulationType, BierInBiftId, BiftId};
use holo_utils::ibus::{BierCfgEvent, SrCfgEvent};
use holo_utils::ip::{AddressFamily, IpNetworkKind};
use holo_utils::mpls::Label;
use holo_utils::sr::{IgpAlgoType, Sid, SidLastHopBehavior};
Expand Down Expand Up @@ -35,8 +36,9 @@ use crate::packet::lsa::{
Lsa, LsaHdrVersion, LsaKey, LsaScope, LsaTypeVersion, PrefixSidVersion,
};
use crate::packet::tlv::{
PrefixSidFlags, RouterInfoCaps, RouterInfoCapsTlv, SidLabelRangeTlv,
SrAlgoTlv, SrLocalBlockTlv,
BierEncapId, BierEncapSubSubTlv, BierSubSubTlv, BierSubTlv, PrefixSidFlags,
RouterInfoCaps, RouterInfoCapsTlv, SidLabelRangeTlv, SrAlgoTlv,
SrLocalBlockTlv,
};
use crate::route::{SummaryNet, SummaryNetFlags, SummaryRtr};
use crate::version::Ospfv3;
Expand Down Expand Up @@ -279,6 +281,23 @@ impl LsdbVersion<Self> 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(())
Expand Down Expand Up @@ -717,6 +736,7 @@ fn lsa_orig_intra_area_prefix(
arenas: &InstanceArenas<Ospfv3>,
) {
let sr_config = &instance.shared.sr_config;
let bier_config = &instance.shared.bier_config;
let lsdb_id = LsdbId::Area(area.id);
let extended_lsa = instance.config.extended_lsa;
let adv_rtr = instance.state.router_id;
Expand Down Expand Up @@ -817,6 +837,60 @@ fn lsa_orig_intra_area_prefix(
}
}

// Add BIER Sub-TLV(s) if BIER is enabled and allowed to advertise
if instance.config.bier.enabled && instance.config.bier.advertise {
bier_config
.sd_cfg
.iter()
// Search for subdomain configuration(s) for current prefix
.filter(|((_, af), sd_cfg)| {
af == &AddressFamily::Ipv6 && sd_cfg.bfr_prefix == prefix
})
.for_each(|((sd_id, _), sd_cfg)| {
// BIER prefix has configured encap ?
let bier_encaps = sd_cfg
.encap
.iter()
.filter_map(|((bsl, encap_type), encap)| {
match encap_type {
BierEncapsulationType::Mpls => {
// TODO: where is the label defined?
Some(BierEncapId::Mpls(Label::new(0)))
}
_ => match encap.in_bift_id {
BierInBiftId::Base(id) => Some(id),
BierInBiftId::Encoding(true) => Some(0),
_ => None,
}
.map(|id| {
BierEncapId::NonMpls(BiftId::new(id))
}),
}
.map(|id| {
BierSubSubTlv::BierEncapSubSubTlv(
BierEncapSubSubTlv::new(
encap.max_si,
id,
(*bsl).into(),
),
)
})
})
.collect::<Vec<BierSubSubTlv>>();

let bier = BierSubTlv::new(
*sd_id,
sd_cfg.mt_id,
sd_cfg.bfr_id,
sd_cfg.bar,
sd_cfg.ipa,
bier_encaps,
);

entry.bier.push(bier);
});
}

prefixes.push(entry);
}
let ref_lsa = LsaKey::new(
Expand Down
Loading

0 comments on commit 1d3461c

Please sign in to comment.