@@ -14,9 +14,14 @@ use std::time::Instant;
1414use bitflags:: bitflags;
1515use derive_new:: new;
1616use holo_utils:: UnboundedSender ;
17+ use holo_utils:: bier:: {
18+ BierEncapId , BierEncapsulationType , BierInBiftId , BiftId ,
19+ UnderlayProtocolType ,
20+ } ;
1721use holo_utils:: ip:: { AddressFamily , Ipv4NetworkExt , Ipv6NetworkExt } ;
22+ use holo_utils:: mpls:: Label ;
1823use holo_utils:: task:: TimeoutTask ;
19- use ipnetwork:: { Ipv4Network , Ipv6Network } ;
24+ use ipnetwork:: { IpNetwork , Ipv4Network , Ipv6Network } ;
2025
2126use crate :: adjacency:: AdjacencyState ;
2227use crate :: collections:: { Arena , LspEntryId } ;
@@ -26,9 +31,12 @@ use crate::interface::{Interface, InterfaceType};
2631use crate :: northbound:: notification;
2732use crate :: packet:: consts:: LspFlags ;
2833use crate :: packet:: pdu:: { Lsp , LspTlvs , Pdu } ;
34+ use crate :: packet:: subtlvs:: prefix:: {
35+ BierEncapSubSubTlv , BierInfoSubTlv , BierSubSubTlv ,
36+ } ;
2937use crate :: packet:: tlv:: {
30- ExtIpv4Reach , ExtIsReach , IpReachTlvEntry , Ipv4Reach , Ipv6Reach , IsReach ,
31- MAX_NARROW_METRIC , Nlpid ,
38+ ExtIpv4Reach , ExtIsReach , IpReachTlvEntry , Ipv4Reach , Ipv6Reach ,
39+ Ipv6ReachSubTlvs , IsReach , MAX_NARROW_METRIC , Nlpid ,
3240} ;
3341use crate :: packet:: { LanId , LevelNumber , LevelType , LspId } ;
3442use crate :: spf:: { SpfType , VertexId } ;
@@ -211,6 +219,7 @@ fn lsp_build_tlvs(
211219 let mut ext_ipv4_reach = BTreeMap :: new ( ) ;
212220 let mut ipv6_addrs = BTreeSet :: new ( ) ;
213221 let mut ipv6_reach = BTreeMap :: new ( ) ;
222+ let bier_config = & instance. shared . bier_config ;
214223
215224 // Add supported protocols.
216225 if instance. config . is_af_enabled ( AddressFamily :: Ipv4 ) {
@@ -329,14 +338,83 @@ fn lsp_build_tlvs(
329338 ipv6_addrs. insert ( addr. ip ( ) ) ;
330339
331340 let prefix = addr. apply_mask ( ) ;
341+
342+ let mut sub_tlvs: Ipv6ReachSubTlvs = Default :: default ( ) ;
343+
344+ // Add BIER Sub-TLV(s) if BIER is enabled and allowed to
345+ // advertise
346+ if instance. config . bier . enabled
347+ && instance. config . bier . advertise
348+ {
349+ bier_config
350+ . sd_cfg
351+ . iter ( )
352+ . filter ( |( ( _, af) , sd_cfg) | {
353+ af == & AddressFamily :: Ipv6
354+ && sd_cfg. bfr_prefix == IpNetwork :: V6 ( prefix)
355+ // Enforce RFC8401 Section 4.2
356+ && sd_cfg. bfr_prefix . prefix ( ) == 128
357+ && sd_cfg. underlay_protocol
358+ == UnderlayProtocolType :: IsIs
359+ } )
360+ . for_each ( |( ( sd_id, _) , sd_cfg) | {
361+ let bier_encaps = sd_cfg
362+ . encap
363+ . iter ( )
364+ . filter_map ( |( ( bsl, encap_type) , encap) | {
365+ match encap_type {
366+ BierEncapsulationType :: Mpls => {
367+ // TODO: where is the label defined?
368+ Some ( BierEncapId :: Mpls ( Label :: new (
369+ 0 ,
370+ ) ) )
371+ }
372+ _ => match encap. in_bift_id {
373+ BierInBiftId :: Base ( id) => Some ( id) ,
374+ BierInBiftId :: Encoding ( true ) => {
375+ Some ( 0 )
376+ }
377+ _ => None ,
378+ }
379+ . map ( |id| {
380+ BierEncapId :: NonMpls ( BiftId :: new (
381+ id,
382+ ) )
383+ } ) ,
384+ }
385+ . map (
386+ |id| {
387+ BierSubSubTlv :: BierEncapSubSubTlv (
388+ BierEncapSubSubTlv :: new (
389+ encap. max_si ,
390+ ( * bsl) . into ( ) ,
391+ id,
392+ ) ,
393+ )
394+ } ,
395+ )
396+ } )
397+ . collect :: < Vec < BierSubSubTlv > > ( ) ;
398+
399+ let bier = BierInfoSubTlv :: new (
400+ sd_cfg. bar ,
401+ sd_cfg. ipa ,
402+ * sd_id,
403+ sd_cfg. bfr_id ,
404+ bier_encaps,
405+ ) ;
406+ sub_tlvs. bier . push ( bier) ;
407+ } )
408+ }
409+
332410 ipv6_reach. insert (
333411 prefix,
334412 Ipv6Reach {
335413 metric,
336414 up_down : false ,
337415 external : false ,
338416 prefix,
339- sub_tlvs : Default :: default ( ) ,
417+ sub_tlvs,
340418 } ,
341419 ) ;
342420 }
0 commit comments