@@ -286,6 +286,9 @@ impl Peer {
286286mod tests {
287287 use super :: * ;
288288 use crate :: bgp:: msg:: Message ;
289+ use crate :: bgp:: msg_update:: { AsPathSegment , AsPathSegmentType , Origin , UpdateMessage } ;
290+ use crate :: peer:: fsm:: BgpState ;
291+ use std:: net:: Ipv4Addr ;
289292
290293 #[ test]
291294 fn test_admin_shutdown_notification ( ) {
@@ -298,4 +301,97 @@ mod tests {
298301 assert_eq ! ( bytes[ 1 ] , 2 ) ; // AdministrativeShutdown subcode
299302 assert_eq ! ( bytes. len( ) , 2 ) ; // No data
300303 }
304+
305+ #[ tokio:: test]
306+ async fn test_update_rejected_in_non_established_states ( ) {
307+ // RFC 4271 Section 9: "An UPDATE message may be received only in the Established state.
308+ // Receiving an UPDATE message in any other state is an error."
309+ use crate :: peer:: states:: tests:: create_test_peer_with_state;
310+
311+ let non_established_states = vec ! [
312+ BgpState :: Connect ,
313+ BgpState :: Active ,
314+ BgpState :: OpenSent ,
315+ BgpState :: OpenConfirm ,
316+ ] ;
317+
318+ for state in non_established_states {
319+ let mut peer = create_test_peer_with_state ( state) . await ;
320+ peer. config . send_notification_without_open = true ;
321+
322+ let update = UpdateMessage :: new (
323+ Origin :: IGP ,
324+ vec ! [ AsPathSegment {
325+ segment_type: AsPathSegmentType :: AsSequence ,
326+ segment_len: 1 ,
327+ asn_list: vec![ 65001 ] ,
328+ } ] ,
329+ Ipv4Addr :: new ( 10 , 0 , 0 , 1 ) ,
330+ vec ! [ ] ,
331+ None ,
332+ None ,
333+ false ,
334+ vec ! [ ] ,
335+ ) ;
336+
337+ let result = peer. handle_message ( BgpMessage :: Update ( update) ) . await ;
338+
339+ assert ! (
340+ result. is_err( ) ,
341+ "UPDATE should cause error in {:?} state" ,
342+ state
343+ ) ;
344+ assert_eq ! (
345+ peer. state( ) ,
346+ BgpState :: Idle ,
347+ "Peer should transition to Idle after UPDATE in {:?}" ,
348+ state
349+ ) ;
350+ assert_eq ! (
351+ peer. statistics. notification_sent, 1 ,
352+ "FSM error NOTIFICATION should be sent in {:?}" ,
353+ state
354+ ) ;
355+ }
356+ }
357+
358+ #[ tokio:: test]
359+ async fn test_update_accepted_in_established ( ) {
360+ // RFC 4271 Section 9: UPDATE is processed normally in Established state
361+ use crate :: peer:: states:: tests:: create_test_peer_with_state;
362+
363+ let mut peer = create_test_peer_with_state ( BgpState :: Established ) . await ;
364+ peer. fsm . timers . start_hold_timer ( ) ;
365+
366+ let update = UpdateMessage :: new (
367+ Origin :: IGP ,
368+ vec ! [ AsPathSegment {
369+ segment_type: AsPathSegmentType :: AsSequence ,
370+ segment_len: 1 ,
371+ asn_list: vec![ 65001 ] ,
372+ } ] ,
373+ Ipv4Addr :: new ( 10 , 0 , 0 , 1 ) ,
374+ vec ! [ ] ,
375+ None ,
376+ None ,
377+ false ,
378+ vec ! [ ] ,
379+ ) ;
380+
381+ let result = peer. handle_message ( BgpMessage :: Update ( update) ) . await ;
382+
383+ assert ! (
384+ result. is_ok( ) ,
385+ "UPDATE should be accepted in Established state"
386+ ) ;
387+ assert_eq ! (
388+ peer. state( ) ,
389+ BgpState :: Established ,
390+ "Peer should remain in Established state"
391+ ) ;
392+ assert_eq ! (
393+ peer. statistics. notification_sent, 0 ,
394+ "No NOTIFICATION should be sent for valid UPDATE"
395+ ) ;
396+ }
301397}
0 commit comments