Skip to content

Commit

Permalink
bier: Add encpasulation sub-sub-tlv for 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 6, 2024
1 parent 6f96f18 commit 4c73ced
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 24 deletions.
66 changes: 59 additions & 7 deletions holo-ospf/src/ospfv3/lsdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,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::ip::{AddressFamily, IpNetworkKind};
use holo_utils::mpls::Label;
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, BierSubTlv,
BierEncapId, BierEncapSubSubTlv, BierSubSubTlv, BierSubTlv, PrefixSidFlags,
RouterInfoCaps, RouterInfoCapsTlv, SidLabelRangeTlv, SrAlgoTlv,
SrLocalBlockTlv,
};
use crate::route::{SummaryNet, SummaryNetFlags, SummaryRtr};
use crate::version::Ospfv3;
Expand Down Expand Up @@ -820,12 +822,62 @@ fn lsa_orig_intra_area_prefix(

// Add BIER Sub-TLV(s)
if instance.config.bier.enabled {
bier_config.sd_cfg.iter().for_each(|((sd_id, addr_family), sd_cfg)|{
if addr_family == &AddressFamily::Ipv6 && sd_cfg.bfr_prefix == prefix {
let bier = BierSubTlv::new(*sd_id, sd_cfg.mt_id, sd_cfg.bfr_id, sd_cfg.bar, sd_cfg.ipa);
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)| {
if let Some(id) = 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
}
}
} {
Some(BierSubSubTlv::BierEncapSubSubTlv(
BierEncapSubSubTlv::new(
encap.max_si,
id,
(*bsl).into(),
),
))
} else {
None
}
})
.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);
Expand Down
8 changes: 4 additions & 4 deletions holo-ospf/src/ospfv3/packet/lsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ use crate::packet::lsa::{
PrefixSidVersion,
};
use crate::packet::tlv::{
tlv_encode_end, tlv_encode_start, tlv_wire_len, AdjSidFlags, GrReason,
GrReasonTlv, GracePeriodTlv, MsdTlv, PrefixSidFlags, RouterFuncCapsTlv,
RouterInfoCapsTlv, RouterInfoTlvType, SidLabelRangeTlv, SrAlgoTlv,
SrLocalBlockTlv, SrmsPrefTlv, UnknownTlv, TLV_HDR_SIZE, BierSubTlv,
tlv_encode_end, tlv_encode_start, tlv_wire_len, AdjSidFlags, BierSubTlv,
GrReason, GrReasonTlv, GracePeriodTlv, MsdTlv, PrefixSidFlags,
RouterFuncCapsTlv, RouterInfoCapsTlv, RouterInfoTlvType, SidLabelRangeTlv,
SrAlgoTlv, SrLocalBlockTlv, SrmsPrefTlv, UnknownTlv, TLV_HDR_SIZE,
};
use crate::version::Ospfv3;

Expand Down
107 changes: 94 additions & 13 deletions holo-ospf/src/packet/tlv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::collections::{BTreeMap, BTreeSet};
use bitflags::bitflags;
use bytes::{Buf, BufMut, Bytes, BytesMut};
use derive_new::new;
use holo_utils::bier::BiftId;
use holo_utils::bytes::{BytesExt, BytesMutExt};
use holo_utils::mpls::Label;
use holo_utils::sr::{IgpAlgoType, Sid};
Expand Down Expand Up @@ -293,6 +294,13 @@ pub struct BierSubTlv {
pub bfr_id: u16,
pub bar: u8,
pub ipa: u8,
pub subtlvs: Vec<BierSubSubTlv>,
}

#[derive(Clone, Debug, Eq, new, PartialEq)]
#[derive(Deserialize, Serialize)]
pub enum BierSubSubTlv {
BierEncapSubSubTlv(BierEncapSubSubTlv),
}

//
Expand All @@ -310,14 +318,50 @@ pub struct BierSubTlv {
// |BS Len | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Bier Non-MPLS Encapsulation Sub-Tlv
//
// Encoding format:
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Type | Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Max SI | BIFT-id |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |BS Len | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
#[derive(Clone, Debug, Eq, new, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct BierMplsEncapSubTlv {
pub struct BierEncapSubSubTlv {
pub max_si: u8,
pub label: Label,
pub id: BierEncapId,
pub bs_len: u8,
}

#[derive(Clone, Debug, Eq, new, PartialEq)]
#[derive(Deserialize, Serialize)]
pub enum BierEncapId {
Mpls(Label),
NonMpls(BiftId),
}

impl BierEncapId {
fn get(self) -> u32 {
match self {
Self::Mpls(label) => label.get(),
Self::NonMpls(bift_id) => bift_id.get(),
}
}
}

#[derive(FromPrimitive, ToPrimitive)]
pub enum BierSubTlvType {
MplsEncap = 41,
NonMplsEncap = 42,
}

#[derive(Clone, Debug, Eq, new, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct UnknownTlv {
Expand All @@ -336,10 +380,11 @@ impl BierSubTlv {
let bar = buf.get_u8();
let ipa = buf.get_u8();
let _reserved = buf.get_u16();
let mut subtlvs: Vec<BierSubSubTlv> = Vec::new();

while buf.remaining() >= TLV_HDR_SIZE as usize {
// Parse Sub-TLV type.
let _stlv_type = buf.get_u16();
let stlv_type = buf.get_u16();

// Parse and validate Sub-TLV length.
let stlv_len = buf.get_u16();
Expand All @@ -348,17 +393,36 @@ impl BierSubTlv {
return Err(DecodeError::InvalidTlvLength(stlv_len));
}

// TODO
// Parse Sub-TLV value.
/*let mut buf_stlv = buf.copy_to_bytes(stlv_wlen as usize);
match stlv_type {
SUBTLV_BIER_MPLS_ENCAP => {
},
_ => {
let mut buf_stlv = buf.copy_to_bytes(stlv_wlen as usize);
match BierSubTlvType::from_u16(stlv_type) {
Some(stlv_type) => {
match stlv_type {
BierSubTlvType::MplsEncap
| BierSubTlvType::NonMplsEncap => {
let max_si = buf_stlv.get_u8();
let id = buf_stlv.get_u24();
let bs_len = (buf_stlv.get_u8() & 0xf0) >> 4;

let id = match stlv_type {
BierSubTlvType::MplsEncap => {
BierEncapId::Mpls(Label::new(id))
}
BierSubTlvType::NonMplsEncap => {
BierEncapId::NonMpls(BiftId::new(id))
}
};
subtlvs.push(BierSubSubTlv::BierEncapSubSubTlv(
BierEncapSubSubTlv { max_si, id, bs_len },
));
}
};
}
None => {
// Ignore unknown Sub-TLV
continue;
}
}*/

}
}

Ok(BierSubTlv {
Expand All @@ -367,19 +431,36 @@ impl BierSubTlv {
bfr_id,
bar,
ipa,
subtlvs,
})
}

pub(crate) fn encode(&self, buf: &mut BytesMut, stlv_type: impl ToPrimitive) {
pub(crate) fn encode(
&self,
buf: &mut BytesMut,
stlv_type: impl ToPrimitive,
) {
let start_pos = tlv_encode_start(buf, stlv_type);
buf.put_u8(self.sub_domain_id);
buf.put_u8(self.mt_id);
buf.put_u16(self.bfr_id);
buf.put_u8(self.bar);
buf.put_u8(self.ipa);
buf.put_u16(0);
// TODO: encode sub-tlvs
tlv_encode_end(buf, start_pos);
for subtlv in &self.subtlvs {
match subtlv {
BierSubSubTlv::BierEncapSubSubTlv(encap) => {
let start_pos =
tlv_encode_start(buf, BierSubTlvType::NonMplsEncap);
buf.put_u8(encap.max_si);
buf.put_u24(encap.id.clone().get());
buf.put_u8(encap.bs_len << 4);
tlv_encode_end(buf, start_pos);
}
_ => {}
}
}
}
}

Expand Down
47 changes: 47 additions & 0 deletions holo-utils/src/bier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ use crate::ip::AddressFamily;
pub type SubDomainId = u8;
pub type BfrId = u16;

#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct BiftId(u32);

impl BiftId {
pub const VALUE_MASK: u32 = 0x000FFFFF;

pub fn new(bift_id: u32) -> Self {
Self(bift_id)
}

pub fn get(&self) -> u32 {
self.0 & Self::VALUE_MASK
}
}

#[derive(Clone, Debug, Default)]
#[derive(Deserialize, Serialize)]
pub struct BierCfg {
Expand Down Expand Up @@ -125,6 +141,37 @@ impl TryFromYang for Bsl {
}
}

impl Into<u8> for Bsl {
// Mapping defined in RFC8296, Section 2.1.2
fn into(self) -> u8 {
match self {
Self::_64 => 1,
Self::_128 => 2,
Self::_256 => 3,
Self::_512 => 4,
Self::_1024 => 5,
Self::_2048 => 6,
Self::_4096 => 7,
}
}
}

impl TryFrom<u8> for Bsl {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
1 => Ok(Self::_64),
2 => Ok(Self::_128),
3 => Ok(Self::_256),
4 => Ok(Self::_512),
5 => Ok(Self::_1024),
6 => Ok(Self::_2048),
7 => Ok(Self::_4096),
_ => Err("Not Supported"),
}
}
}

impl TryFromYang for BierEncapsulationType {
fn try_from_yang(value: &str) -> Option<Self> {
match value {
Expand Down

0 comments on commit 4c73ced

Please sign in to comment.