@@ -13,7 +13,7 @@ use std::time::Duration;
1313use arbitrary:: Arbitrary ;
1414use chrono:: { DateTime , Utc } ;
1515use holo_protocol:: InstanceChannelsTx ;
16- use holo_utils:: bgp:: { AfiSafi , RoleName , RouteType , WellKnownCommunities } ;
16+ use holo_utils:: bgp:: { AfiSafi , RouteType , WellKnownCommunities } ;
1717use holo_utils:: ibus:: IbusChannelsTx ;
1818use holo_utils:: socket:: { TTL_MAX , TcpConnInfo , TcpStream } ;
1919use holo_utils:: task:: { IntervalTask , Task , TimeoutTask } ;
@@ -30,7 +30,7 @@ use crate::northbound::notification;
3030use crate :: northbound:: rpc:: ClearType ;
3131use crate :: packet:: attribute:: { AS_TRANS , Attrs } ;
3232use crate :: packet:: iana:: {
33- Afi , CeaseSubcode , ErrorCode , FsmErrorSubcode , Safi ,
33+ Afi , CeaseSubcode , ErrorCode , FsmErrorSubcode , RoleName , Safi ,
3434} ;
3535use crate :: packet:: message:: {
3636 Capability , DecodeCxt , EncodeCxt , KeepaliveMsg , Message ,
@@ -698,7 +698,7 @@ impl Neighbor {
698698 } ) ;
699699 }
700700
701- if let Some ( role) = self . config . role {
701+ if let Some ( role) = self . config . local_role {
702702 capabilities. insert ( Capability :: Role { role } ) ;
703703 }
704704
@@ -814,40 +814,46 @@ impl Neighbor {
814814 ) ) ;
815815 }
816816
817- if let Some ( local_role) = self . config . role
817+ // RFC 9234: Role correctness validation for OPEN messages.
818+ let mut role_correctness = true ;
819+ if let Some ( local_role) = self . config . local_role
818820 && let Some ( Capability :: Role { role : remote_role } ) = msg
819821 . capabilities
820822 . iter ( )
821823 . find ( |cap| matches ! ( cap, Capability :: Role { .. } ) )
822824 {
823- let err = Err ( Error :: NbrRoleMismatch (
824- self . remote_addr ,
825- local_role. to_u8 ( ) . unwrap ( ) ,
826- remote_role. to_u8 ( ) . unwrap ( ) ,
827- ) ) ;
828-
829- // Validate the incoming BGP Role.
830- // ---
831- // Validation 1:
832- // Check if the neighbor had already sent a Role capability,
833- // and if the role capability is same as incoming.
834- if self . remote_role . is_some ( )
835- && self . remote_role != Some ( * remote_role)
825+ // If remote role already exists, it should be same as incoming role.
826+ if let Some ( r_role) = self . remote_role
827+ && r_role != * remote_role
836828 {
837- return err;
829+ // TODO: (RFC 9234 Section 4.2)
830+ // Use error below only when 'strict mode'
831+ // is enabled
832+ //
833+ // let err = Err(Error::NbrRoleMismatch(
834+ // self.remote_addr,
835+ // local_role.to_u8().unwrap(),
836+ // remote_role.to_u8().unwrap(),
837+ // ));
838+ // Should throw error on struct mode.
839+ role_correctness = false ;
838840 }
839841
840- // Validation 2:
841- // Finds if:
842- // 1. Role has been locally configured.
843- // 2. role exists on the incoming message.
844- // 3. If local role and remote role correctly match the RFC 9234.
845- if !RoleName :: validate_role_correctness ( & local_role, remote_role) {
846- return err;
842+ // Valid Role Mappings.
843+ let role_mappings = BTreeMap :: from ( [
844+ ( RoleName :: Provider , RoleName :: Customer ) ,
845+ ( RoleName :: Customer , RoleName :: Provider ) ,
846+ ( RoleName :: Rs , RoleName :: RsClient ) ,
847+ ( RoleName :: RsClient , RoleName :: Rs ) ,
848+ ( RoleName :: Peer , RoleName :: Peer ) ,
849+ ] ) ;
850+
851+ if let Some ( approved_role) = role_mappings. get ( & local_role)
852+ && approved_role == remote_role
853+ && role_correctness
854+ {
855+ self . remote_role = Some ( * remote_role) ;
847856 }
848-
849- // If everything is okay, then we can set the remote role correctly.
850- self . remote_role = Some ( * remote_role) ;
851857 }
852858
853859 Ok ( ( ) )
0 commit comments