Skip to content

Commit

Permalink
bier: Update BIRT from OSPFv3
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas Rybowski <[email protected]>
  • Loading branch information
nrybowski committed Aug 14, 2024
1 parent f9e9c89 commit bd3277e
Show file tree
Hide file tree
Showing 19 changed files with 365 additions and 59 deletions.
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
36 changes: 15 additions & 21 deletions holo-ospf/src/ospfv3/lsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,8 +820,8 @@ fn lsa_orig_intra_area_prefix(
}
}

// Add BIER Sub-TLV(s)
if instance.config.bier.enabled {
// 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()
Expand All @@ -835,35 +835,29 @@ fn lsa_orig_intra_area_prefix(
.encap
.iter()
.filter_map(|((bsl, encap_type), encap)| {
if let Some(id) = match encap_type {
match encap_type {
BierEncapsulationType::Mpls => {
// TODO: where is the label defined?
Some(BierEncapId::Mpls(Label::new(0)))
}
_ => {
if let Some(id) = match encap.in_bift_id {
BierInBiftId::Base(id) => Some(id),
BierInBiftId::Encoding(true) => Some(0),
_ => None,
} {
Some(BierEncapId::NonMpls(BiftId::new(
id,
)))
} else {
None
}
_ => match encap.in_bift_id {
BierInBiftId::Base(id) => Some(id),
BierInBiftId::Encoding(true) => Some(0),
_ => None,
}
} {
Some(BierSubSubTlv::BierEncapSubSubTlv(
.map(|id| {
BierEncapId::NonMpls(BiftId::new(id))
}),
}
.map(|id| {
BierSubSubTlv::BierEncapSubSubTlv(
BierEncapSubSubTlv::new(
encap.max_si,
id,
(*bsl).into(),
),
))
} else {
None
}
)
})
})
.collect::<Vec<BierSubSubTlv>>();

Expand Down
1 change: 1 addition & 0 deletions holo-ospf/src/ospfv3/packet/lsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2372,6 +2372,7 @@ impl LsaIntraAreaPrefix {
// Parse Sub-TLVs.
let stlvs = ExtLsaSubTlvs::decode(&mut buf_tlv)?;
prefix.prefix_sids = stlvs.prefix_sids;
prefix.bier = stlvs.bier;
prefix.unknown_stlvs = stlvs.unknown;

iap.prefixes.push(prefix);
Expand Down
1 change: 1 addition & 0 deletions holo-ospf/src/ospfv3/spf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ impl SpfVersion<Self> for Ospfv3 {
prefix_options: prefix.options,
metric: prefix.metric,
prefix_sids: prefix.prefix_sids,
bier: prefix.bier,
})
})
}
Expand Down
1 change: 0 additions & 1 deletion holo-ospf/src/packet/tlv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,6 @@ impl BierSubTlv {
buf.put_u24(0);
tlv_encode_end(buf, start_pos);
}
_ => {}
}
}
tlv_encode_end(buf, start_pos);
Expand Down
46 changes: 45 additions & 1 deletion holo-ospf/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use std::net::Ipv4Addr;

use bitflags::bitflags;
use derive_new::new;
use holo_utils::ip::IpAddrKind;
use holo_utils::bier::{BierInfo, Bsl, UnderlayProtocolType};
use holo_utils::ip::{IpAddrKind, IpNetworkKind};
use holo_utils::mpls::Label;
use holo_utils::southbound::OspfRouteType;
use holo_utils::sr::IgpAlgoType;
Expand All @@ -23,6 +24,7 @@ use crate::interface::Interface;
use crate::lsdb::{LsaEntry, LSA_INFINITY};
use crate::northbound::configuration::InstanceCfg;
use crate::packet::lsa::{LsaKey, LsaRouterFlagsVersion};
use crate::packet::tlv::BierSubSubTlv;
use crate::spf::{SpfPartialComputation, VertexLsaVersion};
use crate::version::Version;
use crate::{southbound, sr};
Expand All @@ -41,6 +43,7 @@ pub struct RouteNet<V: Version> {
pub sr_label: Option<Label>,
pub nexthops: Nexthops<V::IpAddr>,
pub flags: RouteNetFlags,
pub bier_info: Option<BierInfo>,
}

bitflags! {
Expand Down Expand Up @@ -396,6 +399,7 @@ fn update_rib_intra_area<V>(
sr_label: None,
nexthops: stub.vertex.nexthops.clone(),
flags,
bier_info: None,
};

// Update route's Prefix-SID (if any).
Expand All @@ -416,6 +420,44 @@ fn update_rib_intra_area<V>(
}
}

// Update BIER Routing Table (BIRT)
if instance.config.bier.enabled && instance.config.bier.receive {
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,
})
}
}
});
}

// Try to add or update stub route in the RIB.
route_update(rib, stub.prefix, new_route, instance.config.max_paths);
}
Expand Down Expand Up @@ -483,6 +525,7 @@ fn update_rib_inter_area_networks<V>(
sr_label: None,
nexthops: route_br.nexthops.clone(),
flags: RouteNetFlags::empty(),
bier_info: None,
};

// Update route's Prefix-SID (if any).
Expand Down Expand Up @@ -677,6 +720,7 @@ fn update_rib_external<V>(
sr_label: None,
nexthops: route_asbr.nexthops.clone(),
flags: RouteNetFlags::empty(),
bier_info: None,
};

// Try to add or update external route in the RIB.
Expand Down
17 changes: 14 additions & 3 deletions holo-ospf/src/southbound/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use std::net::IpAddr;
use holo_utils::ibus::{IbusMsg, IbusSender};
use holo_utils::mpls::Label;
use holo_utils::southbound::{
LabelInstallMsg, LabelUninstallMsg, Nexthop, RouteKeyMsg, RouteMsg,
RouteOpaqueAttrs,
BierNbrInstallMsg, LabelInstallMsg, LabelUninstallMsg, Nexthop,
RouteKeyMsg, RouteMsg, RouteOpaqueAttrs,
};

use crate::collections::Arena;
Expand Down Expand Up @@ -94,13 +94,24 @@ pub(crate) fn route_install<V>(
let msg = LabelInstallMsg {
protocol: V::PROTOCOL,
label: *sr_label,
nexthops,
nexthops: nexthops.clone(),
route: None,
replace: true,
};
let msg = IbusMsg::RouteMplsAdd(msg);
let _ = ibus_tx.send(msg);
}

// Install BIER neighbor entry
if let Some(bier_info) = &route.bier_info {
let msg = BierNbrInstallMsg {
bier_info: bier_info.clone(),
nexthops,
prefix: (*destination).into(),
};
let msg = IbusMsg::RouteBierAdd(msg);
let _ = ibus_tx.send(msg);
}
}

pub(crate) fn route_uninstall<V>(
Expand Down
3 changes: 2 additions & 1 deletion holo-ospf/src/spf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::interface::Interface;
use crate::lsdb::{LsaEntry, LsaLogId};
use crate::neighbor::Neighbor;
use crate::packet::lsa::{Lsa, LsaKey};
use crate::packet::tlv::{SidLabelRangeTlv, SrAlgoTlv};
use crate::packet::tlv::{BierSubTlv, SidLabelRangeTlv, SrAlgoTlv};
use crate::route::{Nexthops, PathType, RouteRtr};
use crate::version::Version;
use crate::{area, route, tasks};
Expand Down Expand Up @@ -73,6 +73,7 @@ pub struct SpfIntraAreaNetwork<'a, V: Version> {
pub prefix_options: V::PrefixOptions,
pub metric: u16,
pub prefix_sids: BTreeMap<IgpAlgoType, V::PrefixSid>,
pub bier: Vec<BierSubTlv>,
}

#[derive(Debug)]
Expand Down
2 changes: 2 additions & 0 deletions holo-ospf/tests/packet/ospfv3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ static LSA2: Lazy<(Vec<u8>, Lsa<Ospfv3>)> = Lazy::new(|| {
value: IpNetwork::from_str("2.2.2.2/32").unwrap(),
metric: 0,
prefix_sids: Default::default(),
bier: vec![],
unknown_stlvs: vec![],
}],
unknown_tlvs: vec![],
Expand Down Expand Up @@ -892,6 +893,7 @@ static EXT_INTRA_AREA_PREFIX_LSA1: Lazy<(Vec<u8>, Lsa<Ospfv3>)> =
}
}
},
bier: vec![],
unknown_stlvs: vec![],
}],
unknown_tlvs: vec![],
Expand Down
3 changes: 3 additions & 0 deletions holo-routing/src/ibus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ pub(crate) fn process_msg(master: &mut Master, msg: IbusMsg) {
.rib
.redistribute_request(protocol, af, &master.ibus_tx);
}
IbusMsg::RouteBierAdd(msg) => {
master.birt.bier_nbr_add(msg);
}
// Ignore other events.
_ => {}
}
Expand Down
5 changes: 4 additions & 1 deletion holo-routing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use tokio::sync::mpsc;
use tracing::Instrument;

use crate::northbound::configuration::StaticRoute;
use crate::rib::Rib;
use crate::rib::{Birt, Rib};

pub struct Master {
// Northbound Tx channel.
Expand All @@ -53,6 +53,8 @@ pub struct Master {
pub bier_config: BierCfg,
// Protocol instances.
pub instances: BTreeMap<InstanceId, NbDaemonSender>,
// BIER Routing Table (BIRT)
pub birt: Birt,
}

#[derive(Debug, Eq, Hash, PartialEq, PartialOrd, new, Ord)]
Expand Down Expand Up @@ -134,6 +136,7 @@ pub fn start(
sr_config: Default::default(),
bier_config: Default::default(),
instances: Default::default(),
birt: Default::default(),
};

// Request information about all interfaces addresses.
Expand Down
1 change: 1 addition & 0 deletions holo-routing/src/northbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ impl ProviderBase for Master {
"ietf-segment-routing-common",
"ietf-segment-routing-mpls",
"ietf-bier",
"holo-routing",
]
}

Expand Down
57 changes: 56 additions & 1 deletion holo-routing/src/northbound/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use holo_northbound::state::{
Callbacks, CallbacksBuilder, ListEntryKind, Provider,
};
use holo_northbound::yang::control_plane_protocol;
use holo_northbound::yang::routing::ribs;
use holo_northbound::yang::routing::{birts, ribs};
use holo_northbound::{CallbackKey, NbDaemonSender};
use holo_utils::bier::{BfrId, Bsl};
use holo_utils::mpls::Label;
use holo_utils::protocol::Protocol;
use holo_utils::southbound::{Nexthop, RouteOpaqueAttrs};
Expand All @@ -37,6 +38,12 @@ pub enum ListEntry<'a> {
Route(RouteDestination<'a>, &'a Route),
Nexthop(&'a Nexthop),
Label((usize, &'a Label)),
SubDomainId(u8),
BfrId(BfrId),
// FIXME: Should be Bsl but issue with yang-rs
Bsl(u8),
BirtEntry((u8, IpAddr, IpAddr)),
BirtKey((u8, u16, Bsl)),
}

#[derive(Debug)]
Expand Down Expand Up @@ -279,6 +286,54 @@ fn load_callbacks() -> Callbacks<Master> {
label: Some(label.to_yang()),
})
})
.path(birts::birt::PATH)
.get_iterate(|master, _args| {
let iter = master.birt.entries.keys().map(|(sd_id, _bfr_id, _bsl)| ListEntry::SubDomainId(*sd_id));
Some(Box::new(iter))
})
.get_object(|_master, args| {
use birts::birt::Birt;
let sub_domain_id = args.list_entry.as_sub_domain_id().unwrap();
Box::new(Birt{sub_domain_id: *sub_domain_id})
})
.path(birts::birt::bfr_id::PATH)
.get_iterate(|master, args| {
let sd_id_arg = *args.parent_list_entry.as_sub_domain_id().unwrap();
let iter = master.birt.entries.keys().filter_map(move |(sd_id, bfr_id, _bsl)| {
if *sd_id == sd_id_arg {
Some(ListEntry::BfrId(*bfr_id))
} else {
None
}
});
Some(Box::new(iter))
})
.get_object(|_master, args| {
use birts::birt::bfr_id::BfrId;
let bfr_id = args.list_entry.as_bfr_id().unwrap();
Box::new(BfrId{bfr_id: *bfr_id})
})
.path(birts::birt::bfr_id::birt_entry::PATH)
.get_iterate(|master, args| {
let bfr_id_arg = *args.parent_list_entry.as_bfr_id().unwrap();
let iter = master.birt.entries.keys().filter_map(move |(sd_id, bfr_id, bsl)| {
if *bfr_id == bfr_id_arg {
Some(ListEntry::BirtKey((*sd_id, *bfr_id, *bsl)))
} else {
None
}
});
Some(Box::new(iter))
})
.get_object(|master, args| {
use birts::birt::bfr_id::birt_entry::BirtEntry;
let birt_key = args.list_entry.as_birt_key().unwrap();
let birt_entry = master.birt.entries.get(birt_key).unwrap();
let bsl = birt_key.2;
let bfr_prefix = Some(Cow::Borrowed(&birt_entry.bfr_prefix));
let bfr_nbr = Some(Cow::Borrowed(&birt_entry.bfr_nbr));
Box::new(BirtEntry{bsl: bsl.into(), bfr_prefix, bfr_nbr})
})
.build()
}

Expand Down
Loading

0 comments on commit bd3277e

Please sign in to comment.